transaction is not getting roll backed with jta transaction manager - java

I am new to Spring and hibernate please help,
I am using (Jboss 6.0 Final as Server)
org.springframework.transaction.jta.JtaTransactionManager
as bean with properties set
transactionManagerName as java:/TransactionManager and
userTransactionName as java:comp/UserTransaction.
In code I have set jtaTxManager property thr setters.
Then
javax.transaction.TransactionManager tx = jtaTxManager.getTransactionManager();
and then transaction is started using tx.begin() statement.
I have used sessionFactory.getCurrentSession() to get session of hibernate
at last I have used
tx.commit()
I am using hibernate to save multiple records within jta transaction
but If in between any database error occurs between some record like constraint violation exception getting thrown on tx.commit() which is javax.transaction.RollbackException which when catch I used to call tx.rollback() but my transaction is not getting rollback and getting following exception on tx.rollback().I have not set any type auto commit property in hibernate properties.
But my first of records in gets saved in database ideally they should not saved but while rollback this exception occurs so i think that's why they are getting saved.
java.lang.IllegalStateException: BaseTransaction.rollback - [com.arjuna.ats.internal.jta.transaction.arjunacore.notx] [com.arjuna.ats.internal.jta.transaction.arjunacore.notx] no transaction!
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.rollback(BaseTransaction.java:158)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.rollback(BaseTransactionManagerDelegate.java:114)

This issue was due to datasource configuration, forgot to mentioned earlier,
Removed from application-context.xml
org.springframework.jdbc.datasource.DriverManagerDataSource
and rather than this, used jndi datasorce of jboss configured in oracle-xa-ds.xml

The Javadoc states that the RollbackException gets thrown when the transaction has been rolledback instead of commited - you don't have to rollback it manually in such a case, I think.
http://download.oracle.com/javaee/6/api/javax/transaction/Transaction.html#commit%28%29

Related

What does SessionFactory do internally when crud operations get called in given application?

I was understanding about spring + hibernate + java integration. So i got clear picture on below given points:
Spring uses LocalSessionFactoryBean class to create SessionFactory which is hibernate class.
Application context load the definition for datasource, hibernate properties etc.
we can inject SessionFactory class in spring dao classes.
My question is on crud operation invocation, like
sessionfactory.getCurrentSession().get(--, -)
How it works internally in terms of using datasource or any other spring/hibernate related resources ?
I try to explain at hight level what happen, for more detail you can check the source code.
First of all in your line of code 2 methods are called:
getCurrrentSession() on session factory
get(--,--) in the returned session
In the first method hibernate use the CurrentSessionContext to retreive the acual session. The CurrentSessionContext implementation substantially looks if there is an open session with an open transaction related to your thread and your session facotry and return it; to make it simpler it loooks if you are doing something on this DB in this thread and allow You to continue. If the CurrentSessionContext doesn't find a session a new one is create. (Note there are many implementation of CurrentSessionContext by default JPA one is used)
After retreive the session the second method is executed. In the second method referring to the dialect and other objects a native sql query is generated. In your specific case the sql is sent over the session to the database, the step looks like:
if the session is not binded to a connection, ask for a db connection from the pool
send the sql over the connection and retreive a resultset
get the resultset and tranlaste it to the entity object wich will be returned
if you are doing a dml operation (update, insert ...) the sql is tored on the session and it will be sent after flushing the session(you can use the flush() method it, otherwise just commit and wait hibernate do ti for you). Important note, committing the Transaction means that the code will be execute on the DB. After commit hibernate, with his own timing, will open a transaction over the db connection (important hibernate transacion is not a db transaction) will execute all the generate sql statement and will commit the DB transaction. This is the flush operation, remember yo don't exactally know when the flush happen since you don't force it manually with the flush() method.
hope this hepl
r.

How JPA with type is JTA handled by EJB container

I used jboss, and hibernate 4 within jpa (JTA transaction type). In a DAOUtil class, I try to get entity manager, I can get it and do a query. But when I flush entity manager, the error happened.
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:970)
at com.vms.dao.hibernate.HibernateDAOSession.flush(HibernateDAOSession.java:288)
I searched on internet, and they say: if we use jpa with jta transaction type, we must inject EntityManager into a ejb, is this correct?
If this is correct, I've a concern: how about threadpool for entity manager? I confused alot of thing about that.
Please anyone give my the true way, to use jpa within JTA transaction type.
Added.
I think this issue because I've a getter to get EntityManager outside EJB.
One more question, in JPA with JTA transaction type, I think we could not update by native sql. IN ejb I've below code.
public int executeNativeUpdate(String query, Map<String, Object> params) {
Query q = em.createNativeQuery(query);
setParameters(q, params);
return q.executeUpdate();
}
Error raised when running into code:
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
Anyone can explain. I'm beginer in JPA adn JTA. If I use JPA with JTA transaction type and inject the EntityManager into Stateless EJB, EJB container will handle transaction for me, right? I no need do begin/commit a transaction. How about native sql? Can EJB container handle all?
If you use JTA transactional type then container manage transactions (application server, or openjpa, or other). In this case you should use EJB, where every method call is wraped in transaction. Create, commit, rollback, manage entity manager - work of container.

Java JPA annotation #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) not working as expected

Running J2EE application on JBoss 5.1 using Hibernate. I need to call some methods (in quartz scheduler) that use explicit database connections from an enterprise bean. Currently get an error about calling commit not allowed in a transaction.
I was hoping that adding the #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) annotation to the bean method would allow me to call quartz api, but still get the same exception. Am I misunderstanding what this annotation means, or is something else going on?
2014-06-23 17:43:41,184 ERROR [http-0.0.0.0-8443-4] org.quartz.JobPersistenceException: Couldn't commit jdbc connection. You cannot commit during a managed transaction! [See nested exception: java.sql.SQLException: You cannot commit during a managed transaction!]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.commitConnection(JobStoreSupport.java:3661)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3799)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeWithoutLock(JobStoreSupport.java:3703)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.checkExists(JobStoreSupport.java:1897)
at org.quartz.core.QuartzScheduler.checkExists(QuartzScheduler.java:1491)
at org.quartz.impl.StdScheduler.checkExists(StdScheduler.java:555)
Some more data:
1) If I call my managed bean method from a non-managed class without the annotation, then I get the same exception (transaction is created)
2) If I call my managed bean method from a non-managed class with the annotation then I dont get the exception (no transaction created)
3) If I call my managed bean method from another managed bean or from itself, then I get the exception with or without the annotation (transaction exists)
So the annotation does seem to prevent a new transaction being created, but it does not seem to suspend an already existing transaction (or maybe I am getting this all wrong).

Hibernate and currentSession: "Heck, I don't want these transactions!"

I substituted:
sessionFactory.openSession();
With:
sessionFactory.getCurrentSession();
And I added this configuration for Hibernate:
<property name="hibernate.current_session_context_class">thread</property>
Now I'm getting this error:
failureorg.hibernate.HibernateException: createQuery is not valid without active transaction
Why should I use beginTransaction() and so on, after I use currentTransaction? I don't want to use transactions... so, what should I change?
You used getCurrentSession, not currentTransaction. Transactions are not optional in Hibernate—you must start a transaction.
The configuration you set up resulted in a session being opened for you automatically, but not a transaction within the session.
You can, skip beginning and committing of transactions by spring integration and declaring your transaction as annotation driven

Why can I insert/update data with hibernate even when there's no transaction involved?

As we all know that in Hibernate if no transaction commit, the changes won't affect in database. But I found something weird. And the code as follows:
ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring.xml");
SessionFactory sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
Session session = sessionFactory.openSession();
Model model = new Model();
...
session.save(model);
session.flush();
session.close();
And the model was saved to database even there's no transaction, anyone can explain this?
Any comments would be appreciated! Thanks!
PS: I am using mysql.
The session.flush command saved the transaction. If it's wrong, you should use transaction.
usually hibernate needs the line session.beginTransaction(); to work. You didn't write that and your application worked, I guess your application runs in an Application server, which provides transaction management. e.g. jboss, weblogic...
However it doesn't mean that there is no transaction. Did you set auto-commit true?
btw, session.flush() and txn.commit() are different.
Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.
After session.flush(), you still can call txn.rollback() to rollback all changes.
edit
oh I saw you used spring. did you configured txnmanager in spring?
Hibernate doesn't need transactions, the most common problems in database-based applications are just easier to solve with transactions which is why usually everyone uses transactions with Hibernate. But that's mere coincidence/convention/laziness.
All Hibernate needs is a java.sql.Connection and if your container provides one even though there is no current transaction manager configured, Hibernate is fine with that.
In fact, Hibernate has no idea that there might be a transaction manager. So session.flush() will use the ApplicationContext to get a connection, generate the SQL and use JDBC to send the generated SQL code to the database.
From Hibernate's point of view, that's all that happens.
There can be several reasons why the data is committed to the database:
You forgot to turn of auto commit on the connection.
Your web container / spring config automatically wires a transaction manager that synchronizes with HTTP requests.
Your code is called form another method which is annotated with #Transactional; in this case, you inherit the existing transaction.

Categories

Resources