Reputation: 3253
I'm using Hibernate 5.2.1 and Spring 4.3.0
My current understanding is:
.flush()
, .clear()
, .openSession()
/.getCurrentSession()
one might
.persist()
ed object which is not and will not be written to the database.persist()
ed objectsI have spent way too much time on not so merry bug hunts that ended in me realizing I was missing a @Transactional
annotation, missed to configure a sensible transaction mode or failed to configure a transaction manager in Spring.
I do not want to engage in the mind-numbing activity of memorizing to never forget to painstreakingly check my transaction code.
I do want my software to be robust enough to tell me when I am doing something stupid or am forgetting something and not just silently fail and drop into an undefined behaviour mode.
Is it possible to make hibernate loudly complain when it's missing a transaction?
Am I approaching this the wrong way? Have I misunderstood anything?
Just for reference:
Upvotes: 0
Views: 724
Reputation: 2500
Hibernate community says that working outside of transaction might cause unpredictable behavior. This is because Hibernate will open transaction, but it won't close it on its own, thus connection will be returned to the Connection Pool with transaction being not committed. What happens then? JDBC keeps silence, thus this is implementation specific (MySQL rolls back transaction, Oracle afair commits it). This also can be configured on Connection Pool level (e.g. C3P0 gives you such an option, rollback by default).
Is it possible to make hibernate loudly complain when it's missing a transaction?
You need to set the logging threshold to DEBUG for the following classes:
For JDBC transactions (e.g. RESOURCE_LOCAL)
For SLF4J logging:
<logger name="org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction" level="debug"/>
For Log4j:
<logger name="org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction">
<level value="DEBUG"/>
</logger>
For JTA transactions
For SLF4J logging:
<logger name="org.hibernate.engine.transaction.internal.jta.JtaTransaction" level="debug"/>
For Log4j:
<logger name="org.hibernate.engine.transaction.internal.jta.JtaTransaction">
<level value="DEBUG"/>
</logger>
In the logs you will see the following entries:
when the transaction starts:
DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - initial autocommit status: true
DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - disabling autocommit
when the transaction ends:
DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - committed JDBC Connection
DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - re-enabling autocommit
It's better to activate the DEBUG level for as few classes as possible, because otherwise your logs size will increase dramatically.
Am I approaching this the wrong way? Have I misunderstood anything?
If you may forget @Transactional
in somewhere, try hibernate with autocommit=true
which fails hardly on stupid codes and remembers you.
Or you may use aspectj
to make all DAOs methods transactional.
Upvotes: 1