使用JDBC乘以表插入

时间:2016-05-19 11:46:12

标签: java mysql jdbc

我正在尝试使用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();
    }

}

1 个答案:

答案 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的优点。

希望这会让事情变得清晰......