entityManager.getTransaction().rollback() detaches entities? - java

I have the following piece of code:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test")
EntityManager entityManager = emf.createEntityManager()
User user = entityManager.find(User.class, 0);
entityManager.getTransaction().begin();
entityManager.getTransaction().rollback();
entityManager.refresh(user);
This throws an IllegalArgumentException on the fourth line saying "Entity not managed". If I change the third line to .commit() instead of .rollback(), everything seems to work fine.
What is going on here? Can I prevent this from happening?
UPDATE: #DataNucleus is directing me towards PersistenceContext. How do I change the persistence context in my code?

From the JSR-000317 Persistence Specification for Eval 2.0 Eval:
3.3.2 Transaction Rollback
For both transaction-scoped and extended persistence contexts, transaction rollback causes all pre-existing managed instances and removed instances
[31]
to become detached. The instances’ state will be the
state of the instances at the point at which the transaction was rolled back. Transaction rollback typically
causes the persistence context to be in an inconsistent state at the point of rollback. In particular, the
state of version attributes and generated state (e.g., generated primary keys) may be inconsistent.
Instances that were formerly managed by the persistence context (including new instances that were
made persistent in that transaction) may therefore not be reusable in the same manner as other detached
objects—for example, they may fail when passed to the merge operation.
[32]

In a PersistenceContext of "Transaction" then commit/rollback will detach objects used in the transaction. In PersistenceContext of "Extended" then commit/rollback do nothing like that, and objects are detached at close of the EM. Depends on your context

Related

Is em.persist() or em.merge() not needed or not for update?

I have the code from below and wondering how does JPA know to persist this update. I expected an em.merge() to be needed in order to perform the update. Is this actually safe ?
#Stateless
class User {
...
public void generateRandomNicknames() {
List<UserEntity> users = em.createNamedQuery("UserEntity.getAllUsers", UserEntity.class)
.getResultList();
for (UserEntity user : users) {
user.setNickname(generateRandomNickname());
}
// em.merge(user) or em.persist(user) not needed ?
}
}
In short: Managed entities are generally synchronized with the database on transaction commit. The JPA implementation is responsible for tracking changed managed entities and update the database. In your case, calling user.setNickname(...) will notify JPA that this specific user object is dirty. And a transaction is by default active on calling business methods of a Session EJB.
Note that the above is the default behavior that can be altered by configuration!
Longer story, with references from the JEE 8 sub-specs (the question is about JEE 6, these still apply, although in different section numbers):
(JPA 2.1) Section 3.2.4: Synchronization to the Database
The state of persistent entities is synchronized to the database at transaction commit. This synchronization
involves writing to the database any updates to persistent entities and their relationships as specified
above.
[...]The persistence provider runtime is permitted to perform synchronization to the database at other times
as well when a transaction is active and the persistence context is joined to the transaction. The flush
method can be used by the application to force synchronization.
There are other interesting details in this chapter, but note that merge() does NOT have to be called, for a managed entity to be saved at the end of the transaction.
Which brings us to the next detail, the transaction. Since this is a method of a Session EJB, it is by default run in the context of a transaction:
(EJB core 3.2) Section 8.3.6: Specification of a Bean’s Transaction Management Type
By default, a session bean or message-driven bean has container managed transaction demarcation if the transaction management type is not specified. [...]
(EJB core 3.2) Section 8.3.7: Specification of the Transaction Attributes for a Bean’s Methods
The Bean Provider of an enterprise bean with container-managed transaction demarcation may specify the transaction attributes for the enterprise bean’s methods. By default, the value of the transaction attribute for a method of a bean with container-managed transaction demarcation is the REQUIRED transaction attribute, and the transaction attribute does not need to be explicitly specified in this case.
An important detail is that the entities are actually managed. This is, in this case, because they are returned from JPA itself and because of how the JPQL query "UserEntity.getAllUsers" is structured. In general entities could be unmanaged or detached, in which case calling merge() or persist() would have been necessary.

JPA EntityTransaction flush

I would like to flush all the entites stored in the current transaction to the database (without ending the current transaction via commit).
Do I need to check if the transaction is Active before doing so?
if (this.entityTransaction.isActive())
{
this.entityManager.flush();
}
Thank you
According to the javadoc of the method flush of eclipselink's EntityManager class:
https://www.eclipse.org/eclipselink/api/2.6/javax/persistence/EntityManager.html#flush()
void flush()
Synchronize the persistence context to the underlying database.
Throws:
TransactionRequiredException - if there is no transaction or if the entity manager has not been joined to the current transaction
PersistenceException - if the flush fails
So yes it looks like you need to check, other ways you might get an exception of type "TransactionRequiredException"

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.

When using a new JTA Transaction, what happens to PersistenceContexts in other transactions?

I'm using CMT with a stateless EJB. Suppose I have two methods, one of which is a timeout for an EJB timer and one which modifies existing entities:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Timeout
public void cullOldEntities() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaDelete<T> cd = cb.createCriteriaDelete(clazz);
Root<T> root = cd.from(clazz);
Path<Date> dateCreatedPath = root.get("lastUpdated");
cd.where(cb.lessThan(dateCreatedPath, dateOfExpiry()));
em.createQuery(cd).executeUpdate();
}
public void modifyEntities(...)
As cullOldEntities requires a new transaction, a new persistence context is created and then it is committed when the method ends. The issue is what happens to a preexisting persistence context of another transaction.
If modifyEntities and then cullOldEntities are called so they run concurrently what happens to modifyEntities persistence context if cullOldEntities finishes first and has it's persistence context committed?
Does the modifyEntities's persistence context get synchronized with the changes made?
If not what will happen when an entity is modified?
How can I do a bulk delete that is safe with concurrent modification?
EntityManager not thread safe. So, without Locking last commit will override changes which was made in another transaction.
The behaviour (and subsequent effect on design of transaction propagation) depends upon the type of scope being used for persistence context. The two kinds are Transaction scoped and Extended Persistence context (which can span multiple transactions). For Transaction scoped persistence context - before the cullOldEntities() method call starts,
the container will suspend the transaction inherited if any and will start a new
transaction (because of attribute TransactionAttributeType.REQUIRES_NEW). When the entity manager method requiring a transaction is invoked on the entity manager, it will check the current transaction for an active persistence context and none will be found. A new
persistence context will be created starting with that call, and this persistence context will be the
active persistence till the method contextcullOldEntities() ends. Because the transaction
started in cullOldEntities() is different from the earlier one ( if there was one) , the entities managed by the previous persistence context
will not be visible to this new one.
An extended persistence context however is typically scoped to the stateful session bean to which it is bound.
the extended entity manager of a stateful session bean always uses the same persistence
context. The stateful session bean is associated with a single extended persistence context that is
created when the bean instance is created and closed when the bean instance is removed.

JTA with PersistenceUnit

Can #PersistenceUnit be used with JTA in JPA? If so, how is it possible?
Per http://tomee.apache.org/jpa-concepts.html:
With <persistence-unit transaction-type="RESOURCE_LOCAL"> [...]
You must use the EntityManagerFactory to get an EntityManager
[...]
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
With <persistence-unit transaction-type="JTA"> [...]
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
I have a similar code which uses JTA and #PersistenceUnit at the same time. But sometimes I am having NullPointerException when accesing transaction (defined as #Resource).
Using JTA means that you delegate the work to the container. You can override it by using a UserTransaction. Your quotation contains all the answers you want to know. Using PersistenceUnit to get an EntityManager won't work.
If you are using RESOURCE_LOCAL you are responsible for the transaction itself, by using EntityManager.getTransaction(). An entity manager is created by an EntityManagerFactory. To obtain that factory, you can use PersistenceUnit.
So the simple answer is no, if you rely on container managed entity managers.
As example see http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
Application Managed Entity Managers = RESOURCE_LOCAL can use UserTransaction (which are part of JTA).
What does entity manager means???
If i am a naive programmer i could simply interpret something which manages entity & Indeed it means the same.
An Entity Manager is been instantiated with the help of an Entity Manager Factory. A connection to a database is managed by the entity manager i.e. it provides functionality for performing operations on a database. Therefore we could say if an application needs multiple database connections, an EntityManagerFactory will be constructed for a specific database which provides an efficient way to construct multiple EntityManager instances(if required, even single instance of entity manager can the job depending upon the requirement you may opt for multiple instances) for that database required for every HTTP request. We shall understand this with the help of an example. Suppose we have a
Database : A , having a relational tables B and C.
So for A, an instance of entity manager factory will be instantiated. Now we if ever want to perform any update to table B & lets say delete operation for table C, either two different entity manager could be instantiated or same the entity manager instance can be utilized for both.
The instantiation of Entity Manager Factory itself is considered to be less efficient but since it's a one time activity therefore it's manageable task because Entity Manager Factory once instantiated, it will serve the entire application
The entity manager instantiated is associated with a persistence context.
#PersistenceUnit(unitName = "MyDatabase")
EntityManagerFactory emf;
EntityManager entityManager = emf.createEntityManager();
or
#PersistenceContext(unitName = "MyDatabase")
private EntityManager entityManager;
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
EntityManagerFactory defines another method for instantiation of EntityManager that, like the factory, takes a map of properties as an argument. This form is useful when a user name and a password other than the EntityManagerFactory's default user name and password have to specified:
Map properties = new HashMap();
properties.put("javax.persistence.jdbc.user", "kashyap");
properties.put("javax.persistence.jdbc.password","kashyap");
EntityManager em = emf.createEntityManager(properties);
Within the persistence context, the entity instances and their lifecycle are managed. By Entity instance, we mean instance of an entity & each entity designates relational table in the database. Entity Manager is actually an interface which provides methods to create and remove persistent entity instances, to find entities by their primary key, and to query over entities so together these functionalities are grouped under operations we perform. Operations that modify the content of a database require active transactions. Transactions are managed by an Entity Transaction instance obtained from the EntityManager.
Precise Definition :-
An Entity Manager is defined by a persistence unit. A persistence unit defines the set of all classes that are related or grouped by the application, and which must be colocated in their mapping to a single database.
Below i'm writing a code snippet for better understanding :-
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction
/**
*getTransaction() EntityManager's method Return the resource-level EntityTransaction object. See JavaDoc Reference Page
*/
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
Lets proceed as per JPA Specification :-
1) Extended vs Transactional - Scoped :
By Default the Transactional Persistence Context is in used which means all changes are flushed and all managed entities become detahced when the current transaction commits.
The Extended scope is available only for Stateful EJBs & it even makes a perfect sense since stateful beans can save the state therefore one can say end of
one business method doesn't necessary means the end of the transaction.
With the Stateless beans, it has a different aspect - We have business method that must end when the business method finishes.
===> One Method = One Transaction;
Only Transactional-Scoped Entity Manager is allowed for Stateless Beans
You can control if the EntityManager is extended or transactional during the EntityManager Injection :-
#PersistenceContext (type = javax.persistence.PersistenceContextType.EXTENDED)
EntityManager emng;
By Default it's javax.persistence.PersistenceContextType.TRANSACTION
Extended and Transaction Scoped PersistenceContext are allowed only in case of container-managed EntityManagers.
Time to step up a bit with: Container-managed vs Application-managed
2) Container-managed vs Application-managed :
#PersistenceContext
EntityManager emng;
Above statement authorises Container to inject the entity manager for you, hence Container-Managed.
Alternatively, you can create an EntityManager by yourself using EntityManagerFactory But this time the injection will be bit different -
#PersistenceUnit
EntityManagerFactory emf;
Now to get the EntityManager you need to invoke
emf.createEntityManager();
And here it is - you're using the application managed Persistence Context. Now you're responsible for creation and removal of EntityManagers.
Focus before you read the next para because that's what the tangled context , i'm trying to resolve-
You might use createEntityManager if you want to have control over created EM - e.g. if you need to move the created EntityManager across multiple beans involved in the trasaction - the container won't do it for you and every time you invoke createEntityManager(), you're creating an EntityManager that is connected to the new PersistenceContext. You might use the CDI for EntityManager's sharing.
Stay tuned for Entity Transaction - JPA and Resource-local, will be posting a detailed discussion on it.
Hope it gives a brief idea about the context. & Feel free to post queries.
Read the second part from here

Categories

Resources