我正在尝试使用JDBC插入三个表。我的代码查询在MySQL Workbench中运行良好,但是当我使用PreparedStatement
运行它时,我遇到错误说
您的SQL语法有错误;查看与您的MySQL服务器版本对应的手册,以获得正确的语法
我的查询看起来像
BEGIN;
INSERT INTO user_authentication (enabled, password, username) values (1,'password','username');
SET @userId = LAST_INSERT_ID();
INSERT INTO account(is_active, balance, user_id) values(1,0.0,@userId);
INSERT INTO user_information (email, firstname, lastname, user_id) values ('OLeg@mail.com','Oleg','Oleg',@userId);
INSERT INTO user_authorization (role, user_id) values ('ROLE_USER', @userId);
COMMIT;
似乎错误是由BEGIN;
语句引起的。
如何使用JDBC和PreparedStatement
运行多次插入查询?
整个方法看起来像
@Override
public void save(User user) {
Connection conn = null;
Account account = user.getAccount();
UserInformation information = user.getUserInformation();
Set<UserAuthorization> roles = user.getRoles();
String insertUserQuery = "INSERT INTO user_authentication (enabled, password, username) values (?,?,?);";
String insertAccountQuery = "INSERT INTO account(is_active, balance, user_id) values(?,?,@userId);";
String insertInformationQuery = "INSERT INTO user_information (email, firstname, lastname, user_id) values (?,?,?,@userId);";
String insertRolesQuery = "INSERT INTO user_authorization (role, user_id) values (?, @userId);";
String query = "BEGIN;" + insertUserQuery
+ " SET @userId = LAST_INSERT_ID(); " + insertAccountQuery
+ insertInformationQuery + insertRolesQuery + "COMMIT;";
try {
conn = dataSource.getConnection();
PreparedStatement statement = conn.prepareStatement(query);
statement.setBoolean(1, true);
statement.setString(2, user.getPassword());
statement.setString(3, user.getUsername());
statement.setBoolean(4, true);
statement.setDouble(5, account.getBalance());
statement.setString(6, information.getEmail());
statement.setString(7, information.getFirstName());
statement.setString(8, information.getLastName());
for (UserAuthorization role : roles) {
statement.setString(9, role.getRole().toString());
}
statement.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
答案 0 :(得分:2)
你在这里混淆了一点。您正在尝试执行一个包含多个语句/查询的事务。
您不能简单地连接所有字符串。你有4个不同的插入。因此,您必须在java中为这些插入创建4个(准备好的)语句对象。您将需要一个额外的语句来检索生成的id(对于外键)。
关于BEGIN和COMMIT:您应该使用&#39; commit()&#39; PreparedStatement对象的方法。 见Oracle JDBC tutorial
请注意该行 con.setAutoCommit(假); 在示例中。 JDBC默认启用自动提交,因此您需要先将其关闭。
似乎不自然地三次从一个java方法触发数据库 调用
如果从mysql workbench运行脚本,仍然会执行多个语句/查询。您的(工作台)示例代码&#39;触发&#39; db 7次,这意味着有7个往返工作台&lt; - &gt;数据库中。
是的,但是我需要使用本地变量&#39; @ userId&#39;来插入外键。
最好将生成的密钥读回您的程序,即选择LAST_INSERT_ID()&#39;或者更好地看到question或更好question。然后将其用作插入其他行的参数。
for (UserAuthorization role : roles) {
statement.setString(9, role.getRole().toString());
}
statement.executeUpdate();
不会给你预期的结果。您(重新)一遍又一遍地设置参数(仅在您的程序中,而不是在数据库中)。请参阅本教程的顶部,其中介绍了PreparedStatment的优点。
希望这会让事情变得清晰......