Prepared语句返回false但插入了行?

时间:2014-04-15 15:54:27

标签: java mysql sql prepared-statement

所以这是我的表:

mysql> DESCRIBE app_user;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| username | varchar(40) | NO   | PRI | NULL    |                |
| password | varchar(40) | NO   |     | NULL    |                |
| email    | varchar(40) | NO   | PRI | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
4 rows in set

mysql> 

我期待的是,我不应该添加具有相同用户名的2行,因为用户名是主键..

这是我的Java代码:

@Test
public void shouldNotInsertWithSameUserName() throws IOException, SQLException {
    AppUserAccessObject appUserAccessObject = new AppUserAccessObject(new DatabaseConnectionImpl());
    Assert.assertFalse(appUserAccessObject.insertUser("koray", "email", "password"));
}

所以这个测试通过了,这意味着insertUser返回false。但是当我检查数据库时,我看到一个新的行。我究竟做错了什么?而insertuser:

public boolean insertUser(String username,String email,String password) throws SQLException {
    PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO "+ tableName + "(username,email,password) VALUES(?,?,?)");
    preparedStatement.setString(1,username);
    preparedStatement.setString(2,email);
    preparedStatement.setString(3,password);
    boolean execute = preparedStatement.execute();
    return execute;
}

1 个答案:

答案 0 :(得分:10)

您的主键基于3个字段:

  • id(具有自动增量值)
  • 用户名
  • 电子邮件

因此,主键限制具有相同值的这3个字段的新行。但由于id标记为自动增量,并且您始终向其发送null,因此它会生成一个新值,因此永远不会让这三个字段具有相同的值。

更好的设计方法是仅将id作为主键,将usernameemail字段设为Unique Key。事实上,拥有两个唯一键会更好:一个用于username,另一个用于email

这样做:

CREATE TABLE app_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username varchar(40),
    password varchar(40),
    email varchar(40),
    UNIQUE KEY (username),
    UNIQUE KEY (email)
);

除了数据库中的设计问题:


  

Prepared语句返回false但是插入了行?

来自PreparedStatement#execute javadoc:

  

如果第一个结果是true对象,则返回ResultSet; false如果第一个结果是更新计数或没有结果。

在这种情况下,您执行更新操作后得到false结果(INSERT被理解为更新操作)。