【问题标题】:jdbc insert into database with auto increment fieldjdbc 使用自动增量字段插入数据库
【发布时间】:2017-08-12 00:33:23
【问题描述】:

我的代码中有这个:

String query
            = "INSERT INTO usermail (FirstName, LastName, Town, Country, Email)  "
            + "VALUES (?, ?, ?, ? ,?)";

我的表如下:

 UserID – AutoNumber (Primary Key)
    FirstName – varchar(15)
    astName – varchar (15)
    Town – varchar(15)
    Country – varchar(15)
    Email – varchar(20)

问题是,当我第一次填写表格时,所有值都会添加到数据库中,但如果我第二次尝试这样做,它们将不会被添加。如果我删除 UserID 表,一切正常。 这就是我创建 UserID 的方式(图片来自 - here

我不确定如何使其与 UserID 一起使用。我无法在其中输入任何内容,因为我的表单中没有这样的字段。

这是我从 stackTrace 得到的

Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   Loading application [MailRegistration] at [/MailRegistration]
Info:   MailRegistration was successfully deployed in 293 milliseconds.
Severe:   com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
    at Data.MailDB.insert(MailDB.java:32)
    at details.DisplayUserDetailsServlet.doPost(DisplayUserDetailsServlet.java:44)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • 默认字段在你的 UI 中代表什么
  • 名称不应该是UserId吗?您是否希望非 id 字段是唯一的?
  • @Ishnark 它是“起始”值
  • @duffymo 是的,这只是示例图片
  • 我很困惑 - 您是否将名称与 UserId 匹配?

标签: java sql jdbc


【解决方案1】:

我使用 MariaDB 解决了您的问题。它工作正常。这是我的表创建 SQL:

create table contact (
  id MEDIUMINT not null AUTO_INCREMENT,
  firstName VARCHAR(64),
  lastName varchar(128),
  city varchar(64),
  state char(2),
  email VARCHAR(64),
  PRIMARY KEY (id)
);

我创建了一个模型对象Contact

package database.mariadb.model;

import org.apache.commons.lang3.builder.ToStringBuilder;

/**
 * Created by Michael
 * Creation date 3/21/2017.
 * @link
 */
public class Contact {

    private Long id;
    private String firstName;
    private String lastName;
    private String city;
    private String state;
    private String email;

    public Contact(String firstName, String lastName, String city, String state, String email) {
        this(null, firstName, lastName, city, state, email);
    }

    public Contact(Long id, String firstName, String lastName, String city, String state, String email) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.city = city;
        this.state = state;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    public String getEmail() {
        return email;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this)
                .append("id", id)
                .append("firstName", firstName)
                .append("lastName", lastName)
                .append("city", city)
                .append("state", state)
                .append("email", email)
                .toString();
    }
}

我创建了一个仓库接口:

package database.mariadb.persistence;

import database.mariadb.model.Contact;

import java.util.List;

/**
 * Created by Michael
 * Creation date 3/21/2017.
 * @link
 */
public interface ContactRepository {

    List<Contact> findAll();
    void insert(Contact contact);
}

我实现了接口:

package database.mariadb.persistence;

import database.mariadb.model.Contact;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Michael
 * Creation date 3/21/2017.
 * @link
 */
public class ContactRepositoryImpl implements ContactRepository {

    private static final String FIND_ALL_SQL = "SELECT id, firstName, lastName, city, state, email from  contact ";
    private static final String INSERT_SQL = "INSERT INTO contact(firstName, lastName, city, state, email) values(?, ?, ?, ?, ?) ";

    private Connection connection;

    public ContactRepositoryImpl(DataSource dataSource) throws SQLException {
        this.connection = dataSource.getConnection();
    }

    public ContactRepositoryImpl(Connection connection) {
        this.connection = connection;
    }

    @Override
    public List<Contact> findAll() {
        List<Contact> result = new ArrayList<>();
        try (Statement st = connection.createStatement();
             ResultSet rs = st.executeQuery(FIND_ALL_SQL)) {
            while (rs.next()) {
                Long id = rs.getLong("id");
                String firstName = rs.getString("firstName");
                String lastName = rs.getString("lastName");
                String city = rs.getString("city");
                String state = rs.getString("state");
                String email = rs.getString("email");
                result.add(new Contact(id, firstName, lastName, city, state, email));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public void insert(Contact contact) {
        if (contact != null) {
            try (PreparedStatement ps = connection.prepareStatement(INSERT_SQL, Statement.RETURN_GENERATED_KEYS)) {
                ps.setString(1, contact.getFirstName());
                ps.setString(2, contact.getLastName());
                ps.setString(3, contact.getCity());
                ps.setString(4, contact.getState());
                ps.setString(5, contact.getEmail());
                int numRowsAffected = ps.executeUpdate();
                try (ResultSet rs = ps.getGeneratedKeys()) {
                    if (rs.next()) {
                        contact.setId(rs.getLong(1));
                    }
                } catch (SQLException s) {
                    s.printStackTrace();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

JUnit 测试完美运行。

如果我多次插入同一个联系人,我会得到预期的结果:多行具有新的 ID,相同的数据。

【讨论】:

    【解决方案2】:

    当您以这种方式创建表时:

    create table usermail (
     UserID BIGINT NOT NULL AUTO_INCREMENT,
     FirstName varchar(15),
     LastName  varchar(15),
     Town      varchar(15),
     Country   varchar(15),
     Email     varchar(2),
     PRIMARY KEY (UserID)
    );
    

    您应该能够以您尝试过的方式添加记录。 可能它也可以工作,当您单击左侧的检查字段“INCREMENT BY 1”时

    【讨论】:

      【解决方案3】:

      解决这个自增主键问题的简单方案如下: 这里 ID 是整数,但我们可以为第一个 '?' 设置带有空值的字符串。并且请不要提及列名,它将按照表中的列顺序插入值。

         String insertQueryStatement = "INSERT INTO  MATRIX_A VALUES  (?,?,?,?,?)";
         preparedStatement = connection.prepareStatement(insertQueryStatement);
         preparedStatement.setString(1, null);
         preparedStatement.setString(2, entity.getType());
         preparedStatement.setString(3, entity.getGroup());
         preparedStatement.setString(4, entity.getLoss());
         preparedStatement.setString(5, entity.getSeverity());
         preparedStatement.executeUpdate();
      

      【讨论】:

        【解决方案4】:

        我认为您的代码每次运行时都会从相同的数字开始递增(不确定您在哪里生成 Userid)。您可以有一个带有用户 ID 的单独表,并在每次运行程序时递增它。这样,最新的用户 ID 就存储在“用户 ID”表中。

        然后您可以检索此值并插入“usermail”表。像这样的:

        int userid= "Select userid from USERID_TB";
        //Execute query and get value of userid
        String query
                = "INSERT INTO usermail (Userid,FirstName, LastName, Town, Country, Email)  "
                + "VALUES (userid,?, ?, ?, ? ,?)";
        
        String update="update USERID_TB set userid="+(userid+1)+"where userid="+userid";
        

        我使用这种设计来维护用户 ID 列表,因此我始终拥有最新的计数,而不必在我的前端代码中维护它。希望这对你有用!

        【讨论】:

        • 没有人应该以这种方式构造查询字符串。使用 PreparedStatement。你的答案不正确。
        • 我试过了,还是不行。不过感谢您的尝试。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多