Migrating hibernate 3.6 to 5.1 generates exception in HibernateUtils [duplicate] - java

I am working on a Hibernate project.I had used Hibernate 4.3.1 libraries of Netbeans. Then I needed to use Apache Lucene for fulltext searching. To be able to use Lucene I needed to switch to Hibernate 5.x jars.I can define a new Transaction object but wasRollecBack method of Transaction class is not working. I used this method in several places and now I'm stuck. When I look at javadoc of Hibernate 5.0.6 there is nothing like org.hibernate.transaction . There is org.hibernate.engine.transaction but it does not work either.
When I get back to 4.3.1 wasRolledBack is working but this time I cant run project with lucene libraries. I am confused.

wasRolledBack method is not included in the Hibernate 5.0.6 version Transaction interface Here .
4.3.1 version that was taking place in the wasRolledBack method.
Existing methods:
public interface Transaction {
void begin();
void commit();
void rollback();
TransactionStatus getStatus();
void registerSynchronization(Synchronization synchronization) throws HibernateException;
void setTimeout(int seconds);
int getTimeout();
void markRollbackOnly();
}
I did not test, but you can use the getStatus method.
Example:
TransactionStatus transactionStatus = session.getTransaction().getStatus();
if(transactionStatus.equals(TransactionStatus.ROLLED_BACK)){
//action s.a :)
}
EDIT 1:
TransactionStatus Enum Constant and Description:
ACTIVE : The transaction has been begun, but not yet completed.
COMMITTED : The transaction has been competed successfully.
COMMITTING :Status code indicating a transaction that has begun the
second phase of the two-phase commit protocol, but not yet completed
this phase.
FAILED_COMMIT:The transaction attempted to commit, but
failed.
MARKED_ROLLBACK:The transaction has been marked for rollback only.
NOT_ACTIVE:The transaction has not yet been begun
ROLLED_BACK:The transaction has been rolled back.
ROLLING_BACK:Status code indicating a transaction that is in the
process of rolling back.

Related

"javax.persistence.TransactionRequiredException: no transaction is in progress", even with #Transactional; possible to implicitly manage Transactions?

I'm upgrading an old system that is a batch job that uses Camel Spring Main to continue running, so that it can basically loop and query a database every few seconds, and then process those records. It uses Spring for configuration, but doesn't use Spring Boot. It was on Camel 2.x and I'm having to upgrade it to Camel 3.14. Also upgrading from Spring 4 to 5 and Hibernate 4 to 5.
After those upgrades, when I run it, I'm getting this TransactionRequiredException. Have found that a fair amount here; I have added the #Transactional to the method that does the update where the error occurs, but that made no difference.
Found another answer that says you also need context:component-scan in appContext.xml, which I do have.
This answer suggested adding a hibernate property, hibernate.allow_update_outside_transaction = true, which I tried in my app-confix.xml, but it didn't work.
This answer said to add the following code, which I did, and which did fix it:
protected static void storeObject(Object object) throws DAOException {
Transaction tx = null;
try {
Session session = Helper.getHibernateSession();
session.saveOrUpdate(object);
tx = session.beginTransaction();
session.flush();
tx.commit();
} catch (HibernateException he) {
if(tx != null){
tx.rollback();
}
throw new DAOException(he);
}
}
But to add this to every method that does an update seems like a lot of boilerplate, repeated code. Is there any way to implicitly do basic Transactions all the time? I tried configuring #Transactional and #EnableTransactionManagement and configured the supporting #Beans in a #Configuration class, by following the outline here, but still got the TransactionRequiredException: no transaction in progress error.
One article said #Transactional is only available in Spring Boot: is this true?

Use JPA in Java SE application with support for transactions

I am trying to develop a small program that uses JPA, but can run without an application server, i.e. as a regular Java SE application.
AFAIK, for JavaEE the application server takes care of starting and ending database transactions. Now my problem is that I get this error from some internal code using JPA:
Exception in thread "main" javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1171)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1332)
at <see below>
The code causing this exception is equivalent to this:
String persistenceUnitName; // actually comes from some config file
EntityManager entityManager = Persistence.createEntityManagerFactory(persistenceUnitName).createEntityManager();
entityManager.flush(); // exception is thrown here
I cannot change that code, so it relies on a transaction being automagically started.
Wrapping the call to the above code in a custom transaction like this:
String persistenceUnitName; // same persistence unit name
EntityManager entityManager = Persistence.createEntityManagerFactory(persistenceUnitName).createEntityManager();
entityManager.getTransaction().begin();
callAboveCode();
entityManager.getTransaction().commit();
does not help. the call to the factory's createEntityManager() returns a new entity manager each time, resulting in a different persistence context I suppose.
Is there a way to get automatic transactioning, similar to running JPA in an application server, in a Java SE application?
In SE you have to be careful only using one instance of EntityManager in the whole application. Use a singleton ore something similar for managing that instance.
You also have to manage transaction "manually" - like:
em.getTransaction().begin();
em.persist(anyobject);
em.getTransaction().commit();

Spring transaction internals

The situation is as follows:
Method1 has four database update methods in it. The Method1 is annotated using the Spring transaction management semantics.
Method2 has a database read method in it and it is invoked after Method1 has finished executing all its database updates. Method2 is also annotated using the Spring transaction semantics.
There's a web request that comes in, the controller intercepts the request and invokes method1 and then method2.
A transaction is wrapped around the web-request as well.
What I am interested in knowing is:
1.How does Spring know to commit the database updates upon a successful transaction? Is there some reference to the Spring implementation that does the transaction management?
2.Since we have a hierarchy of transactions:
Transaction around the web-request->Transaction with Propagation=RequestNew for Method1->Transaction with Propagation=Required for Method2, how does Spring do the transaction management to ensure the transactions are executed within the proper context with the right order?
In short, it will be great to get a play by play account of how Spring performs the transaction management in all its grittiest details or a reference to documentation that doesn't simply hand-wave an explanation centered around JTA or some other acronym.
Thanks
Lets make some basic statements.
A transactional context is an environment where some special properties (database session) are made available to the application runtime which are otherwise not available. A Transaction Context is generally used to scope a transaction.
Spring uses, AOP Proxies and XML metadata to achieve a Declarative transaction management.
Annotations are used to mark the Transaction Propagation behavior of a particular method.
Spring uses Interceptor Mechanism to apply the transaction over the methods.
Here I am reusing the example give by #stacker above
MyClass{
#Transactional
public void sequence() {
method1();
method2();
}
#Transactional
void method1() {
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
void method2() {
}
}
You can also achieve the same functionality using xml configuration as well. Lets take this as its popular and widely used.
At the time of deployment
Spring framework checks the xml configuration files (famed applicationContext.xml) and depending on the configuration, scans the code for #Transactional annotation (assuming that the configuration is mentioned as annotation based).
After this, it generates AOP proxies for methods marked for transaction. In simple terms, these proxies are nothing but wrapper around the concerned methods.
Within these wrapper methods, before and after a Transaction Advisor code is also generated depending on the configuration (namely the transaction propagation).
Now when these wrapper methods are invoked Transaction Advisor comes into picture before and after the actual method call. .
Representing the same in pseudo code for the example above
ProxyMyClass{
MyClass myclass;
.
.
.
sequence(){
//Transaction Advisor code (Typically begin/check for transaction)
myclass.sequence();
//Transaction Advisor code(Typically rollback/commit)
}
.
.
.
}
This is how spring managers the transaction. A slight oversimplification though.
Now to answer your questions,
.How does Spring know to commit the database updates upon a successful transaction? Is there some reference to the Spring implementation that does the transaction management?
Whenever you call a method under transaction, you actually call a proxy which first executes the transaction advisor (which will begin the transaction), then you call the actual business method, once that completes, another transaction advisor executes (which depending on way method returned, will commit or rollback transaction).
Since we have a hierarchy of transactions: Transaction around the web-request->Transaction with Propagation=RequestNew for Method1->Transaction with Propagation=Required for Method2, how does Spring do the transaction management to ensure the transactions are executed within the proper context with the right order?
In case of transaction hierarchy, the spring framework generates the Transaction Advisor checks accordingly. For the example you mentioned,
for method1 (RequestNew ) Transaction Advsor code (or transaction Advice) would be to create a new transaction always.
for method2 (Required ) Transaction Advisor code (or transaction Advice) would be check for existing transaction and use the same if it exists or else create a new transaction.
There is an image on the spring documentation page which very nicely summarizes these aspects.
Hope this helps.
Controller
#Transactional
public void sequence() {
method1();
method2();
}
#Transactional
void method1() {
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
void method2() {
}
The default propagation is REQUIRED (Support a current transaction, create a new one if none exists.) Therefore m1 will use the Transaction started in the Controller. m2 is annotated as REQUIRES_NEW ( Create a new transaction, suspend the current transaction if one exists.) The order of the transaction is the order you call the transactional methods.
Controller
begin tx1
|--------------------> m1 (uses tx1)
|
| begin tx2
|--------------------> m2 (uses tx2)
| commit tx2
commit tx1
Have you read the Spring documentation? Basically AOP is used to manage the transaction. You should also read the AOP documentation. If the AOP documentation is not enough I suggest you go through the code. Stepping through the code in debug mode with break-point would be good.

JPA / #PostPersist #PostUpdate - transaction

I am currently working with #PostPersist and #PostUpdate, and in those triggers I am persisting additional entities. The question is, are those triggers in the same transaction and if not is it possible to force it ?
For me it works this way.
While I was looking through the logs the transaction isn't existing ( it's commited just before the trigger is launched ) which prevents me ( without REQUIRES_NEW on the persisting method from injected bean ) from saving the additional entities in database.
REQUIRED attribute is totally ignored, and MANDATORY attribute do not throw an exception.
Can it be the problem with JUnit ( since I am in the dev. phase and did not test the behavior on full env. ) ?
If extending the transaction on this triggers is not possible, how to ensure that if the rollback occurs before the #PostPersist and #PostUpdate, those operations also will be rollbacked.
If you're using Spring you could always register a TransactionSynchronization with your current transaction manager to be called back on events such as commits of your currently running transaction:
#PostPersist
void onPersist() {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
#Override
public void beforeCommit(boolean readOnly) {
// do work
}
});
}
}
A TransactionSynchronization also provides callbacks after a transaction has committed successfully and before/after a transaction completes.
If you need to inspect if the transaction was committed or rolled back, use afterCompletion(int status).
For details have a look at TransactionSynchronization's JavaDoc.
The firing of a PostPersist event does not indicate that the entity has done a successful commit. The transaction may be rolled back after the firing of the event but before the successful commit.
If you in the PostPersist get the entity manager used in the transaction and then do somehting like this:
#PostPersist
void someMethod() {
EntityManager em = null;
em = getEntityManagerUsedInTransaction();
EntityTransaction et = em.getTransaction(); // should return the current transaction
if (et.isActive() ) {
// do more db stuff
}
}
NB: I haven't tried this so it's only speculation (tho' I have used the lifetime event trigger extensively for other stuff).
I have to add that I don't think this is a good idea. Use the PostPersist to flag that other entities should be persisted and do it in another transaction.

HibernateDaoSupport , transaction is not rolled back

I'm playing around with Spring + Hibernate and some "manual" transaction management with PostgreSQL
I'd like to try this out and understand how this works before moving to aop based transaction management.
#Repository
public class UserDAOImpl extends HibernateDaoSupport implements UserDAO {
#Override
public void saveUser(User u) {
Transaction tx = getSession().beginTransaction();
getHibernateTemplate().saveOrUpdate(u);
tx.rollback();
}
}
Calling saveUser here, I'd assume that saving a new User will be rolled back.
However, moving to a psql command line, the user is saved in the table.
Why isn't this rolled back, What do I have to configure to do transactions this way ?
Edit; a bit more debugging seems to indicate getHibernateTemplate() uses a different session than what getSession() returns (?)
Changing the code to
Transaction tx = getSession().beginTransaction();
getSession().persist(u);
tx.rollback();
and the transaction does get rolled back. But I still don't get why the hibernateTemplate would use/create a new session..
A couple of possibilities spring to mind (no pun intended):
a) Your JDBC driver defaults to autocommit=true and is somehow ignoring the beginTransaction() and rollback() calls;
b) If you're using Spring 3, I believe that SessionFactory.getSession() returns the Hibernate Session object wrapped by a Spring proxy. The Spring proxy is set up on the Session in part to handle transaction management, and maybe it's possible that it is interfering with your manual transaction calls?
While you can certainly use AOP-scoped proxies for transaction management, why not use the #Transactional(readOnly=false|true) annotation on your service layer methods? In your Spring config file for your service layer methods, all you need to do to make this work is to add
<tx:annotation-driven />
See chapters 10 and 13 of the Spring Reference Documentation on Transaction Management and ORM Data Access, respectively:
http://static.springsource.org/spring/docs/3.0.x/reference/index.html
Finally, if you're using Spring 3, you can eliminate references to the Spring Framework in your code by injecting the Spring-proxied SessionFactory bean into your DAO code - no more need to use HibernateDaoSupport. Just inject the SessionFactory, get the current Session, and use Hibernate according to the Hibernate examples. (You can combine both HibernateDaoSupport and plain SessionFactory-based Hibernate code in the same application, if required.)
If you see the JavaDoc for HibernateDaoSupport.getSession() it says it will obtain a new session or give you the one that is used by the existing transaction. In your case there isn't a transaction listed with HibernateDaoSupport already.
So if you use getHibernateTemplate().getSession() instead of just getSession(), you should get the session that is used by HibernateTemplate and then the above should work.
Please let me know how it goes.
EDIT:
I agree its protected...my bad. So the other option then is to keep the session thread bound which is usually the best practice in a web application. If HibernateDaoSupport is going to find a thread bound session then it will not create a new one and use the same one. That should let you do rollbacks.

Categories

Resources