Understanding JTA in EJB: No Flushing

So, I have this EJB annotated at the class level with @TransactionAttribute(TransactionAttributeType.REQUIRED) , so that every method should be executed in a transaction, if I do not override this behavior when the transaction is committed, the data is intended to be cleared, right? So far, so good. So now I have a public User find(String email) method annotated with @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) , so this method is not executed in the transaction, as it only retrieves the data.

Ok, so I am testing my application and I have a boot method that creates a pair of entities using ejb and then uses the find method to retrieve. What, in my opinion, should happen:

-> I create an entity 1 that calls save(User u) , which is executed in a transaction. It captures, the data is cleared.

-> Repeat this step with two more objects. their transactions are committed, data is cleared.

-> At this moment, I should have 3 objects in my L2 cache (using Eclipselink) and in my database.

-> I call the find(String email) method. It finds an entity, returns it, does not exclude it, and my code works fine, I'm excited, I open a beer, and I don't need to ask a question in stackoverflow.

What is actually going on:

-> I create all 3 objects. Not an exception.

-> I call the find(String email) method, it throws an EjbException because it does not find the entity, debugging I find that when this method is called, the database is empty, the data was not flushed (even if I call the flush method when I I create entities explicitly, which should not be mandatory in any case). It throws an EJbException, my code stops, I check the database again and NOW that there are entites after the exception was thrown because they were not there. If I remove @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) from the find method, which forces it to search inside the transaction, my code works.

-> I do not open beer.

So seriously, what's going on? Why should I search for an object inside a transaction, otherwise it does not flush anything?

EDIT: Unit of storage:

 <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="TribunalExpedientes" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>tribunalexpedientes</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <shared-cache-mode>ALL</shared-cache-mode> <properties> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence> 

An exception was not excluded, except that it indicated that no objects were found during the search, after which the cache will be flushed to the database.

+4
source share
3 answers

I assume that you do not have the correct settings. Include your persistence.xml and which application server and database you are using.

Whether you use JTA or RESOURCE_LOCAL, you must use JTA and must install the target server in your persistence.xml file.

Also check for errors. If an error occurs, the transaction will be discarded.

NOT_SUPPORTED is not a good idea in general, this means that an exception will be thrown if this method is called in a transaction. It may be what is happening.

+3
source

Add, which will show you when the statements are executed and when the transaction is completed. Since NOT_SUPPORTED pauses the transaction, you can only β€œfind” the data if the previous transaction was committed. Most likely, your save methods are wrapped in a large transaction, which your search method pauses. Flush will not change this because this data is still transaction-isolated.

Try using REQUIRES_NEW so that the save methods are placed in their own transactions that are committed after completion.

+1
source

Well, a transaction does not require Eclipselink to clear data. This is the reason. This, in my opinion, is a very ugly behavior. Eclipselink is allowed to clear data when it wants to. I also had problems with this. For instance. when using @PrePersist or @PreUpdate it is not guaranteed that this happens when a transaction is committed. For instance. when calculating some statistics, you will not be able to use them within a single transaction, since Eclipselink can process when the transaction is already completed.

You must use the object you use to create em.persist (). If you execute a db request. Eclipselink needs to clear the object because the request may be incorrect. But using em.flush () instead will cause some really ugly performance issues when trying to scale the application.

0
source

Source: https://habr.com/ru/post/1402774/


All Articles