【问题标题】:Prepared statement returns false but row is inserted? [duplicate]准备好的语句返回 false 但插入了行? [复制]
【发布时间】:2014-04-16 00:14:53
【问题描述】:

这是我的桌子:

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。但是当我检查数据库时,我看到插入了一个新行。我究竟做错了什么?而插入用户:

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;
}

【问题讨论】:

标签: java mysql sql prepared-statement


【解决方案1】:

您的主键基于 3 个字段:

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

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

对您的表更好的设计是将id 仅用作主键,并将Unique Key 用于您的usernameemail 字段。事实上,最好有两个唯一键:一个用于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)
);

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


准备好的语句返回false,但插入了行?

来自PreparedStatement#executejavadoc:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-13
    • 2012-01-31
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2016-03-07
    相关资源
    最近更新 更多