所以这是我的表:
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;
}
答案 0 :(得分:10)
您的主键基于3个字段:
因此,主键限制具有相同值的这3个字段的新行。但由于id
标记为自动增量,并且您始终向其发送null
,因此它会生成一个新值,因此永远不会让这三个字段具有相同的值。
更好的设计方法是仅将id
作为主键,将username
和email
字段设为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)
);
除了数据库中的设计问题:
PreparedStatement#executeUpdate
执行INSERT
,UPDATE
和DELETE
等DML状态。SELECT
从数据库中检索数据时使用PreparedStatement#executeQuery
。CREATE TABLE
或ALTER TABLE
等任何类型的SQL语句时使用PreparedStatement#execute
。Prepared语句返回false但是插入了行?
来自PreparedStatement#execute
javadoc:
如果第一个结果是
true
对象,则返回ResultSet
;false
如果第一个结果是更新计数或没有结果。
在这种情况下,您执行更新操作后得到false
结果(INSERT
被理解为更新操作)。