Hibernate - ThreadLocal <entitymanager> vs EntityManager每个操作

时间:2016-08-17 07:30:53

标签: java hibernate jpa entitymanager thread-local

我使用Hibernate 5.1.0.Final,Guice,Jersey。我有HibernateModule创建EntityManagerFactory并管理EntityManager个实例:

public class HibernateModule extends AbstractModule {

    private static final ThreadLocal<EntityManager> ENTITY_MANAGER_CACHE = new ThreadLocal<EntityManager>();

    @Provides @Singleton
    public EntityManagerFactory provideEntityManagerFactory(@Named("hibernate.connection.url") String url, 
        @Named("hibernate.connection.username") String userName, 
        @Named("hibernate.connection.password") String password,
        @Named("hibernate.hbm2ddl.auto") String hbm2ddlAuto,
        @Named("hibernate.show_sql") String showSql) {

        Map<String, String> properties = new HashMap<String, String>();
        properties.put("hibernate.connection.driver_class", "org.postgresql.Driver");
        properties.put("hibernate.connection.url", url);
        properties.put("hibernate.connection.username", userName);
        properties.put("hibernate.connection.password", password);
        properties.put("hibernate.connection.pool_size", "1");
        properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        properties.put("hibernate.hbm2ddl.auto", hbm2ddlAuto);
        properties.put("hibernate.show_sql", showSql);
        properties.put("hibernate.cache.use.query_cache", "false");
        properties.put("hibernate.cache.use_second_level_cache", "false");

        return Persistence.createEntityManagerFactory("db-manager", properties);
    }

    @Provides
    public EntityManager provideEntityManager(EntityManagerFactory entityManagerFactory) {

        EntityManager entityManager = ENTITY_MANAGER_CACHE.get();

        if (entityManager == null || !entityManager.isOpen()) 
            ENTITY_MANAGER_CACHE.set(entityManager = entityManagerFactory.createEntityManager());

        entityManager.clear();

        return entityManager;
    }
}

entityManager.clear()用于清除持久性上下文并强制从dabatase查询最新数据。 GenericDAO从HibernateModule接收注入的EntityManager。主要方法:

public class GenericDAOImpl<T> implements GenericDAO<T> {

    @Inject
    protected EntityManager entityManager;

    private Class<T> type;

    public GenericDAOImpl(){}

    public GenericDAOImpl(Class<T> type) {
        this.type = type;
    }

    @Override
    public void save(T entity) {
        entityManager.getTransaction().begin();
        entityManager.persist(entity);
        entityManager.getTransaction().commit();
    }

    @Override
    public T find(Long entityId) {
        return (T) entityManager.find(type, entityId);
    }
}

以前我曾尝试实现一个解决方案,它在每个数据库操作上提供新的EntityManager,但它会导致一些副作用,例如&#34;传递给分离的实体持续存在&#34;。

EntityManager重用ThreadLocal<EntityManager>是一种好习惯吗?这种实现有任何潜在的缺点吗?

1 个答案:

答案 0 :(得分:2)

它应该正常工作。 Spring Framework正在使用ThreadLocalEntityManager。参考:

  

Spring可以轻松创建Session并将其绑定到当前   线程透明

如果要重新使用EntityManager实例,您应该记住JPA提示,PersistenceContextTypeFlushModeType