我正在使用MySQL数据库。以下部分创建记录并从创建的记录中获取id:
insertStmt = connection
.prepareStatement("INSERT INTO bugs (summary, status, report_date) VALUES (?, ?, ? )");
//...
insertStmt.executeUpdate();
idQuery = connection.prepareStatement("SELECT LAST_INSERT_ID()");
rs = idQuery.executeQuery();
if (rs != null) {
rs.next();
return new Long(rs.getLong(1)).toString();
}
现在,如果两个线程执行此操作并且它们的执行是交错的,比如说,第一个线程插入记录,然后插入第二个线程,之后第一个线程调用last_insert_id(),这对于此线程不正确第二个帖子已经插入了一条记录 但是,这可以通过同步来克服。有没有办法在单个数据库调用中执行这两个语句?
答案 0 :(得分:2)
LAST_INSERT_ID
按连接工作,并且正如您的问题所述,如果两个线程中的两个语句使用相同的连接,则可能会出现竞争条件。
你有两种解决方法:
1:每个线程使用一个单独的连接(不容易,但这实际上是扩展和感知的最佳选择;使用连接池)
2:在同一API调用中使用executeUpdate
getGeneratedKeys
的形式,允许您稍后使用LAST_INSERT_ID
进行阅读,这样您就不必使用{{ 1}}在第二个查询中,以避免竞争条件。您可以在准备好的陈述中使用类似的records the auto-generated key形式。
选项2可能是你想要的短期内容。选项2中的链接直接指向该API。 prepareStatement
是一篇MySQL文章,概述了如何使用它。
答案 1 :(得分:0)
根据https://dev.mysql.com/doc/refman/5.7/en/connector-j-reference-configuration-properties.html,您应该能够将?allowMultiQueries=true
添加到JDBC连接字符串中。然后,您将能够在Statement#execute(String sql)
调用中传递多个以分号分隔的语句。
编辑:或者,使用执行所需操作的存储过程。或者,正如您所说,synchronize
Java代码。
答案 2 :(得分:0)
您可以尝试使用Multiquery,将Insert和Select Last_INSERT_ID()组合在同一个字符串中。
1)准备连接以使用multiquery: “JDBC:MySQL的://”, “?allowMultiQueries =真” +主机+ “/” +数据库+
2)将Insert Query与Select:
组合在一起multiQuerySqlString =“INSERT INTO bug(summary,status,report_date)VALUES(1,2,3); SELECT LAST_INSERT_ID()”
3)执行查询并期待多个结果集:
boolean isResultSet = statement.execute();
ResultSet res = statement.getResultSet();
if isResultSet = statement.getMoreResults();
// Second ReulstSet object
res = cs.getResultSet();
我希望它有效
答案 3 :(得分:0)
如果 在一个连接上执行此操作,您可以要求驱动程序返回生成的ID:
insertStmt = connection.prepareStatement("...",PreparedStatement.RETURN_GENERATED_KEYS );
insertStmt.executeUpdate();
ResultSet rs = insertStatement.getGeneratedKeys();
Long id = null;
if (rs != null)
{
rs.next();
id = rs.getLong(1);
}
connection.commit();
return id;
根据驱动程序的不同,您可能需要使用列名作为第二个参数的其他prepareStatement()
调用:
insertStmt = connection.prepareStatement("INSERT ", new String[] {"ID"});
但即使使用上面的代码,您也应该在不同的物理连接上进行并发插入,以便能够正确控制您的事务。