1

I am going crazy about an error in my code involving data persistence in Java (JPA). I didn't develop this and I am not at all knowledgeable about this framework, so, sorry in advance about whatever info I fail to present.

The error in question is that a query created with EntityManager.createQuery (a simply select on a table) returns inconsistent results. That is to say, if I change a value via the interface, save the changes, and then reload the browser again and again, sometimes I will see the new value and sometimes I will see the old value. There seems to be no pattern by which this happens, for all I know it is random. And while this happens, if I query the MySQL database, I always see the correct value (the 'new' value).

I don't know what I should even be looking at. The inconsistent values are retrieved from a class annotated as follows:

@ManagedBean
@ViewScoped
public class DivisoreVolumenticoView implements Serializable {

and the kind of object that this EntityManager.createQuery returns is annotated as follows:

@ManagedBean
@Entity
@Table(name = "divisore_volumetrico")
public class DivisoreVolumetricoBean implements Serializable {

where the inconsistent property (although this would happen with any of them) is:

@Column(name = "nazionale")
private Double nazionale;

and there are a bunch of other methods annotated as @Transient, and the getters and setters for the properties do not have any annotations.

The EntityManager on which createQuery is called is retrieved from class below (and when I execute this on my local environment, with every browser refresh sometimes a new object is created and sometimes it isn't):

public class EMHelper {
    private static final EntityManagerFactory emf;
    private static final ThreadLocal<EntityManager> threadLocal;

    static {
        emf = Persistence.createEntityManagerFactory("persistenceUnit");
        threadLocal = new ThreadLocal<EntityManager>();
    }
    
    public static EntityManager getEntityManager() {
        EntityManager em = threadLocal.get();
        if (em == null) {
            em = emf.createEntityManager();
            threadLocal.set(em);
        }
        return em;
    }

If you can at least point me in the right direction, I'd be very grateful. For example: since the value in the database is always the correct one, should I assume that there is no problem with the persistence of the change? or could the problem be there and the inconsistencies while retrieving it be just a symptom?

Thanks in advance.

javier
  • 62
  • 7
  • 1
    Sharing entity managers through thread locals is problematic if you don't clean them up after a request. Try adding a servlet filter that does something along the lines of `threadLocal.get().close(); theadLocal.remove()` – Christian Beikov Dec 11 '20 at 09:22
  • @ChristianBeikov Hi Christian, thanks so much for answering. Turns out there was already some code meant to close the EntityManager, but it was never being used. Closing after each request seems to have fixed the problem! By the way, just to be clear. You meant I should close not just after `persist` or `merge`, but after each time I run `createQuery`, correct? – javier Dec 11 '20 at 15:19
  • 1
    Usually, a session/entitymanager is transaction scoped. So after commit/rollback you should close it and create a new one when you need it. – Christian Beikov Dec 14 '20 at 08:41

0 Answers0