我想知道是否可以在一个事务中在Hibernate中运行SELECT和UPDATE语句。 有一种非常特殊的情况,我无法改变。所以我必须调用一个SQL函数,然后更新一个表。 此函数创建一些临时内容,用于更新表。 如果未在同一事务中调用,则触发器会导致更新失败。
所以,请不要告诉我,我应该改变这一点:如果可以,我会这样做。 但无论如何......这是我的代码应该在一个事务中运行,但不会这样做:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int nativeUpdateWithParams(String currentUser, boolean setCurrentUser, String nativeSql, Object...obj) {
try {
Query query;
if (nativeSql != null) {
if (setCurrentUser) {
String sql = "SELECT module.current_user(:param1)";
query = em.createNativeQuery(sql);
query.setParameter("param1", currentUser);
query.getSingleResult();
}
query = em.createNativeQuery(nativeSql);
int i=0;
for (Object param:obj) {
i++;
query.setParameter("param"+i, param);
}
int result = query.executeUpdate();
return result;
} else {
return 0;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
return 0;
}
}
Hibernate似乎创建了至少两个执行SELECT和UPDATE的事务。 如果我将Transactionattribute更改为:
@TransactionAttribute(TransactionAttributeType.MANDATORY)
在客户端上创建一个事务(我总是提交...无论发生什么事情) 我写道:
String test = "SELECT module.current_user('userXYZ')";
query = em.createNativeQuery(test + ";" + nativeSql);
我确实得到了类似“更新返回东西......”的执行,但它确实有效。 如果有人可以帮助我解决这个问题,那将是非常好的!
谢谢
编辑: 该异常将无济于事,因为它是“更新”表触发的结果。
Caused by: org.postgresql.util.PSQLException: FEHLER: You are not a real person.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1525)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1309)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:188)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:354)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:308)
at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:210)
... 72 more
详细了解: 如果我在控制台/ Postgres上执行以下操作,它就像一个魅力:
begin transaction;
SELECT module.current_user('userXYZ');
update public.carrier set carrier_comment='whatever' where carrier_id=57300;
commit;
我的作品!
如果我这样做:
SELECT module.current_user('userXYZ');
update public.carrier set carrier_comment='whatever' where carrier_id=57300;
我确实得到了如上所述的错误:“你不是真人”
EDIT2: 如果有人遇到同样的问题,解决方案就像愚蠢一样简单:) 只需检查您的glassfish设置(JDBC - JDBC连接池)并确保您没有激活:
交易:非交易连接:已启用
多数民众赞成。更改此设置后,事务正在按预期工作。所以这不是Hibernate的问题......
问候!
答案 0 :(得分:0)
当然可以。你为什么不能?当你告诉它从数据库中获取一个对象然后更新这个对象时,你认为Hibernate会怎么做?它执行SQL select查询以获取对象,然后执行SQL更新查询以更新它。