在一个Transaction中使用JTA运行本机SELECT和UPDATE

时间:2012-01-17 07:32:19

标签: hibernate transactions

我想知道是否可以在一个事务中在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的问题......

问候!

1 个答案:

答案 0 :(得分:0)

当然可以。你为什么不能?当你告诉它从数据库中获取一个对象然后更新这个对象时,你认为Hibernate会怎么做?它执行SQL select查询以获取对象,然后执行SQL更新查询以更新它。