JPA:如何设置MySQL会话变量?

时间:2018-01-17 09:27:18

标签: java mysql jpa

我需要为我的应用程序设置一个mysql会话变量,以便按预期使用MariaDB Galera Cluster。 SQL调用是:SET SESSION wsrep_sync_wait = 1。应用程序使用数据库时,应始终设置它。我使用EclipseLink作为JPA提供程序。

我的问题是:实现这一目标的最佳方法是什么?

选项1:EclipseLink会话自定义程序

persistence.xml注册会话自定义程序:

public class SessionCustomizerImpl implements org.eclipse.persistence.config.SessionCustomizer {

    private final static String WSREP_SYNC_WAIT_CHECK_SQL = "SHOW SESSION VARIABLES LIKE 'wsrep_sync_wait'";
    private final static String WSREP_SYNC_WAIT_SET_SQL = "SET SESSION wsrep_sync_wait = 1";

    @Override
    public void customize(Session session) throws Exception {
        Vector result = session.executeSQL(WSREP_SYNC_WAIT_CHECK_SQL);
        if ((result != null) && !result.isEmpty()) {
            session.executeNonSelectingSQL(WSREP_SYNC_WAIT_SET_SQL);
            // Galera connection detected; wsrep_sync_wait set to 1
        } else {
            // No Galera connection detected; wsrep_sync_wait not set
        }

    }
}

这对我不起作用。从EntityManager查询会话变量将返回值0

选项2:EntityManager工厂

每次创建新的EntityManager时,都会执行SQL。

public class SyncWaitEntityManagerFactory implements Factory<EntityManager> {
    private final EntityManagerFactory emf;

    @Inject
    public SyncWaitEntityManagerFactory(EntityManagerFactory emf) {
        this.emf = emf;
    }

    @Override
    public EntityManager provide() {
        final EntityManager em = emf.createEntityManager();
        // set it
        em.getTransaction().begin();
        em.createNativeQuery("SET SESSION wsrep_sync_wait = 1").executeUpdate();
        em.getTransaction().commit();

        return em;
    }

    @Override
    public void dispose(EntityManager instance) {
        if (instance.isOpen()) {
            instance.close();
        }
    }

}

这有效,但我不确定它是否有点过分。此外,我担心交易的成本,这只是Query#executeUpdate()所需,而不是实际的SQL调用。

选项3:通过JDBC URL

将变量和值附加到JDBC URL(有关详细信息,请参阅here):

    String jdbcUrl = "jdbc:mysql://db.example.test:3306/"+ JDBC_DB 
            +"?sessionVariables=wsrep_sync_wait=1";
    Properties p = new Properties();
    p.put("javax.persistence.jdbc.url", jdbcUrl);
    p.put("javax.persistence.jdbc.user", JDBC_USER);
    p.put("javax.persistence.jdbc.password", JDBC_PASSWORD);
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPU", p);

    EntityManager entityManager = emf.createEntityManager();

很好的解决方案。适合我;没有努力,没有必要的交易。缺点:我无法捕获异常(例如:首先检查变量是否存在,然后设置它 - 允许在不支持/使用此特定变量的系统上部署代码。)

0 个答案:

没有答案