Search code examples
hibernategrailstransactionsgrails-orm

Grails: how to distinct one transaction from another?


Executing a line of code and another line, how could I tell whether they are executed within the same hibernate transaction or within different? Having current transaction's unique ID available would be an useful feature while investigating hard bugs.

I tried casting TransactionStatus to an implementation DefaultTransactionStatus which has method getTransaction() but that resulted in three HibernateTransactionObject's with different hashCode... Not helpful.

In the example below I wanted to have expressions like status1 ne status2 and status2 eq status3. But equals() returns always false for both TransactionStatus and HibernateTransactionObject:

Dog.withTransaction { TransactionStatus status1 ->
    Dog.withNewTransaction { TransactionStatus status2 ->
        Dog.withTransaction { TransactionStatus status3 ->
            print(status1)
            print(status2)
            print(status3)
        }
    }
}

Output:

org.springframework.transaction.support.DefaultTransactionStatus@d42932c / org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@3f02d1d0
org.springframework.transaction.support.DefaultTransactionStatus@598b083a / org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@dcc3481
org.springframework.transaction.support.DefaultTransactionStatus@5803214e / org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@36c945c3

Grails 2.2.0, Hibernate 3.6


Solution

  • I solved it in a hack-ish way, relying on "connection holder" which is "Transaction-aware proxy for target Connection". I'd be glad to find a cleaner way for sure. For the initial example, this method gives correct UID's: status1 != status2 && status2 == status3. Although I'm not sure it is stable, it could be useful for debugging.

    // groovy code, not java
    int getCurrentTransactionUid(TransactionStatus ts) {
      DefaultTransactionStatus dts = ts
      return dts.transaction.connectionHolder.hashCode()
    }