场景:我遇到了一些在事务中将 JPA 与 JDBC 混合的代码。 JDBC 正在对基本上是空白行的表执行 INSERT,将主键设置为 (SELECT MAX(PK) + 1)
并将 middleName
设置为临时时间戳。然后,该方法从同一个表中选择 max(PK)
+ 该临时时间戳来检查是否存在冲突。如果成功,它将清空 middleName
并更新。该方法返回新创建的主键。
问题: 是否有更好的方法将实体插入数据库,将 PK 设置为 max(pk) + 1 并获取对新创建的 PK 的访问权限(最好使用 JPA)?
环境: 使用EclipseLink并且需要支持Oracle和MS SqlServer数据库的多个版本。
额外背景:我问这个问题的原因是因为在运行时调用此方法作为链的一部分时遇到java.sql.BatchUpdateException
集成测试。链的上半部分使用 JPA EntityManager
来持久化一些对象。
有问题的方法
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int generateStudentIdKey() {
final long now = System.currentTimeMillis();
int id = 0;
try {
try (final Connection connection = dataSource.getConnection()) {
if (connection.getAutoCommit()) {
connection.setAutoCommit(false);
}
try (final Statement statement = connection.createStatement()) {
// insert a row into the generator table
statement.executeUpdate(
"insert into student_demo (student_id, middle_name) " +
"select (max(student_id) + 1) as student_id, '" + now +
"' as middle_name from student_demo");
try (final ResultSet rs = statement.executeQuery(
"select max(student_id) as student_id " +
"from student_demo where middle_name = '" + now + "'")) {
if (rs.next()) {
id = rs.getInt(1);
}
}
if (id == 0) {
connection.rollback();
throw new RuntimeException("Key was not generated");
}
statement.execute("update student_demo set middle_name = null " +
"where student_id = " + id);
} catch (SQLException statementException) {
connection.rollback();
throw statementException;
}
}
} catch (SQLException exception) {
throw new RuntimeException(
"Exception thrown while trying to generate new student_ID", exception);
}
return id;
}
最佳答案
首先:回答这个问题很痛苦。但我知道,有时你必须与魔鬼打交道:(
所以从技术上讲,它不是 JPA,但如果您使用 Hibernate 作为 JPA-Provider,则可以使用
@org.hibernate.annotations.GenericGenerator(
name = “incrementGenerator”,
strategy = “org.hibernate.id.IncrementGenerator”)
@GeneratedValue(generator="incrementGenerator")
private Long primaryKey;
Hibernate 解决方案是“线程安全”的,但不是“集群安全”的,即如果您在多个主机上运行应用程序,则可能会失败。您可以捕获适当的异常并重试。
如果您坚持您的解决方案:关闭 抱歉,最初没有捕获 try-with-resources。ResultSet
、Statement
和 Connection
。
关于java - JPA:如何插入将 PK 设置为 MAX(PK) + 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15852714/