Set Isolation level in eclipselink

2019-05-03 23:58发布

问题:

I would like to set isolation level using eclipse link,
I tried these 2 ways to do it:

  1. java.sql.Connection

    mgr = EMF.get().createEntityManager();
    tx = mgr.getTransaction();
    tx.begin();
    
    java.sql.Connection connection = mgr.unwrap(java.sql.Connection.class);
    connection.setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_COMMITTED);
    System.out.println("Connection: "+connection.getTransactionIsolation());
    //prints TRANSACTION_READ_COMMITED as expected
    
    org.eclipse.persistence.sessions.DatabaseLogin databaseLogin = new DatabaseLogin();
    System.out.println("DatabaseLoging: "+databaseLogin.getTransactionIsolation());
    //prints -1, representing transaction isolation is not set
    
  2. DatabaseLogin setTransationIsolation method

    mgr = EMF.get().createEntityManager();
    tx = mgr.getTransaction();
    tx.begin();
    
    org.eclipse.persistence.sessions.DatabaseLogin databaseLogin = new DatabaseLogin();
    databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_READ_COMMITTED);
    System.out.println("DatabaseLoging: "+databaseLogin.getTransactionIsolation());
    //prints TRANSACTION_READ_COMMITED as expected
    
    java.sql.Connection connection = mgr.unwrap(java.sql.Connection.class);
    System.out.println("Connection: "+connection.getTransactionIsolation());
    //prints TRANSACTION_REPEATABLE_READ
    

As you can see there are some inconsistencies between the return values of getTransacationIsolation() method. My question is, which transaction isolation is really set in both cases ? I know that eclipse link uses different connection for read and write operations by default, DatabaseLogin.setTransactionIsolation should set the isolation level for both connections, so why Connection.getTransactionIsolation still returns another isolation level ?

I am using Application scoped EntityManager, JPA 2.0, EclipseLink 2.5.2.
If there are more preferable ways setting the transaction isolation, please let me know.

回答1:

After having a small pause with eclipse link, I finally found out how to set transaction isolation level.
As @Chris correctly mentioned in his answer I need to obtain DatabaseLogin used by sessions. After a small research on eclipse link sessions I have found out, that I can change the Session properties in my own SessionCustomizer, see the code below:

package com.filip.blabla;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.factories.SessionCustomizer;

public class DFSessionCustomizer implements SessionCustomizer {
        @Override
        public void customize(Session session) throws Exception {
            DatabaseLogin databaseLogin = (DatabaseLogin) session.getDatasourceLogin();
            databaseLogin.setTransactionIsolation(DatabaseLogin.TRANSACTION_READ_COMMITTED);
        }

}

set SessionCustomizer in persistence.xml

<property name="eclipselink.session.customizer" value="com.filip.blabla.DFSessionCustomizer"/>


回答2:

The databaseLogin class is an internal object that EclipseLink uses to configure how it accesses the database, and the settings used to configure those connections. Any changes you make directly to a connection will not be reflected in a DatabaseLogin instance.

Just creating a new DatabaseLoging instance is not going to give you access to the settings being used by the persistence unit. You need to obtain the DatabaseLogin being used by the sessions underneath the the EntityManager/EMF.