Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

JPA: Special considerations for concurrent transactions?

 
Johnny Caimbridge
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

Recently, I've been using JPA with thread local entity managers that create transactions and merge/access entities concurrently on a single database. This has exhibited many issues (deadlock, timeouts, entities simply not being persisted, etc etc), and before going into any of them, I would like to get a general idea of what configuration is necessary for using JPA under such a scenario--on the JPA end and on the database end (in general, of course, as I understand that databases are not uniform). I'm going to tell you up-front that my knowledge of databases is not too extensive.

For an example of the type of considerations I'm looking for: on the Java end, I understand that EntityManagers are not thread-safe. Thus, I use thread-local entity managers.

Unfortunately, anything beyond that is a mystery to me. On various blogs and such, I've run into brief comments on how, for instance, transactions on the JPA end and transactions on the database end should be considered separately, and that there are such things as "transaction isolation levels" that should be configured to the most liberal setting that your application can allow without issues. Still, this is all a big black box to me: I don't know what sort of synchronization JPA or the database should be expected to automatically handle themselves, or what I would need to personally configure. I don't know where to start. Google hasn't been too helpful.

If someone can put me on the right track, it would be very helpful.
 
James Sutherland
Ranch Hand
Posts: 553
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Using an EntityManager concurrently is in general, a very bad idea. An EntityManager should represent a single request or transaction. In some stateful cases it could represent a user session.

In general you should create an EntityManager for a request, use it, commit or rollback the transaction, and throw it away. Storing it in a thread local and using it indefinitely is not a good idea.

What is your architecture, what are doing, and what database are you using?

Perhaps give an example of one of your deadlocks.
 
Johnny Caimbridge
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry for not getting back to you earlier.

Essentially, this is what I'm doing (code to follow):

For a set of 10 or so threads, I dedicate each a "unit of work" consisting of processing some XML, creating entities from that processing, and then persisting those entities. All of these operations are independent of one another. I dedicate each thread its own thread local entity manager obtained from a static method of another class 'PersistCxt'.

This is on a DB2 database, using OpenJPA as a JPAProvider. I'm using an application managed entity manager with resource local transactions in an EE environment.

Originally, I was observing SQL exceptions with an SQL Code indicating deadlock and/or timeout. As of now, I'm only seeing a timeout on the worker threads (without any indication of an SQL exception). This occurs on the call of the merge method:

[1/25/11 15:49:33:882 EST] 000000cb SystemErr <openjpa-1.2.3-SNAPSHOT-r422266:965640 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Connection not available, Timed out waiting for 180212
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4247)<openjpa-1.2.3-SNAPSHOT-r422266:965640 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Connection not available, Timed out waiting for 180010<openjpa-1.2.3-SNAPSHOT-r422266:965640 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Connection not available, Timed out waiting for 180338
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4247) at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4247)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4212) at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4212)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4212) at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:504)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102) at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:504) at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:504)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102) at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
[1/25/11 15:49:33:882 EST] 000000c6 SystemErr at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88) at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88) at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88)
[1/25/11 15:49:33:882 EST] 000000c6 SystemErr at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.connect(JDBCStoreManager.java:934)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getConnection(JDBCStoreManager.java:230)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:371)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:325)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getInitializeStateResult(JDBCStoreManager.java:503) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.connect(JDBCStoreManager.java:934) at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.connect(JDBCStoreManager.java:934) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initializeState(JDBCStoreManager.java:322) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getConnection(JDBCStoreManager.java:230)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initialize(JDBCStoreManager.java:278) at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:371)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getConnection(JDBCStoreManager.java:230) at com.ibm.ws.persistence.jdbc.kernel.WsJpaJDBCStoreManager.initialize(WsJpaJDBCStoreManager.java:144)
[1/25/11 15:49:33:882 EST] 000000c6 SystemErr at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:325) at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:371) at org.apache.openjpa.kernel.DelegatingStoreManager.initialize(DelegatingStoreManager.java:111)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.sql.SelectImpl.execute(SelectImpl.java:325)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getInitializeStateResult(JDBCStoreManager.java:503) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.getInitializeStateResult(JDBCStoreManager.java:503)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.kernel.ROPStoreManager.initialize(ROPStoreManager.java:57) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initializeState(JDBCStoreManager.java:322)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initialize(JDBCStoreManager.java:278) at org.apache.openjpa.kernel.BrokerImpl.initialize(BrokerImpl.java:913) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initializeState(JDBCStoreManager.java:322)
[1/25/11 15:49:33:882 EST] 000000c4 SystemErr at com.ibm.ws.persistence.jdbc.kernel.WsJpaJDBCStoreManager.initialize(WsJpaJDBCStoreManager.java:144) at org.apache.openjpa.kernel.BrokerImpl.find(BrokerImpl.java:871)
[1/25/11 15:49:33:882 EST] 000000cb SystemErr at org.apache.openjpa.kernel.BrokerImpl.find(BrokerImpl.java:793) at org.apache.openjpa.kernel.DelegatingStoreManager.initialize(DelegatingStoreManager.java:111) at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.initialize(JDBCStoreManager.java:278)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.BrokerImpl.isDetached(BrokerImpl.java:4316)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.VersionAttachStrategy.attach(VersionAttachStrategy.java:78)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:241)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:101)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.BrokerImpl.attach(BrokerImpl.java:3242)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.kernel.DelegatingBroker.attach(DelegatingBroker.java:1158)
[1/25/11 15:49:33:898 EST] 000000cb SystemErr at org.apache.openjpa.persistence.EntityManagerImpl.merge(EntityManagerImpl.java:775)



And now for the code:

persistence.xml


Entity



PersistCxt.java


Example driver code for each thread




This is why I'm curious as to whether or not there are any special considerations needed for concurrent transactions. I've read up on DB2 and it's so called "contexts," but I'm not sure what JPA guarantees/does not guarantee as far as concurrent transactions go (and consequently what special considerations I need to make).
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic