简体   繁体   English

JPA / Hibernate动态注入实体管理器

[英]JPA/Hibernate dynamically injecting entity manager

I have a JPA/hibernate setup with multiple entity managers. 我有一个带有多个实体管理器的JPA /休眠设置。 What I am trying to do is dynamically injecting the entity manager in an abstract class used by multiple schemas with the same entity definition -- the tables are exactly the same across different databases in a single MySQL server. 我想要做的是将实体管理器动态地注入具有相同实体定义的多个模式所使用的抽象类中-这些表在单个MySQL服务器中的不同数据库中完全相同。 I am trying not to write unnecessary duplicate code, but I can't seem to find a way to inject the persistence context dynamically without duplicating a lot of code. 我试图不编写不必要的重复代码,但似乎无法找到一种无需重复大量代码即可动态注入持久性上下文的方法。 Is there any way to do this? 有什么办法吗?

Well, do you need to change the EntityManager that exists in a DAO instance? 那么,您是否需要更改 DAO实例中存在的EntityManager? If yes, I'd say just switch your connection pool instead. 如果是,我想说的只是切换您的连接池。

If instead you want to select to which instance to connect, set up the necessary keys in one or more profiles, then use that to get the necessary connection properties for your connection pool. 相反,如果您要选择连接到哪个实例,请在一个或多个配置文件中设置必要的键,然后使用该键为您的连接池获取必要的连接属性。

If you want to have multiple instance of the same DAO, use qualified beans and constructor injection to get the proper entity managers to them (abstract away everything else like factory / pool creation into methods). 如果要具有同一个DAO的多个实例,请使用合格的bean和构造函数注入为它们提供适当的实体管理器(将工厂/池创建等其他所有内容抽象为方法)。

I ended up creating an abstract DAO with all the basic list, update, delete methods and extending by another abstract DAO in which I set the entity manager for that particular set. 我最终创建了一个包含所有基本列表,更新,删除方法的抽象DAO,并通过另一个抽象DAO进行了扩展,在其中我为该特定集合设置了实体管理器。 Any DAOs that extend the last one will have the correct annotated entity manager associated with them. 任何扩展最后一个DAO的DAO都将具有与之关联的正确的带注释的实体管理器。 From that point on I am able to reuse my models, and all I have to do is extend the right DAO on my service layer. 从那时起,我可以重用我的模型,而我要做的就是在服务层上扩展正确的DAO。

The magic happens by calling setEntityManager(EntityManager em) using the @PerisstenceContext with the persistence unitName. 魔术通过使用@PerisstenceContext和持久性unitName调用setEntityManager(EntityManager em)来实现。 I am not entirely sure why this works, but seems to do the trick. 我不完全确定为什么这样做,但似乎可以解决问题。

Here's what I did: AbstractJpaDao: 这是我所做的:AbstractJpaDao:

@MappedSuperclass
public class AbstractJpaDao <T>{
    private Class<T> clazz;
    protected EntityManager entityManager;

    public final void setClazz(final Class<T> clazzToSet) {
        this.clazz = clazzToSet;
    }

    @Transactional
    public T getById(final long id) {
        return entityManager.find(clazz, id);
    }
    //... all the others ...
}

InheritedDao1: InheritedDao1:

@MappedSuperclass
public class InheritedDao <T> extends AbstractJpaDao <T>{
    //This is what allows me to inject the entityManager by its annotation
    @PersistenceContext(unitName = "myPU")
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

InheritedDao2: InheritedDao2:

@MappedSuperclass
public class OtherInheritedDao <T> extends AbstractJpaDao <T>{
    //This is what allows me to inject the entityManager by its annotation
    @PersistenceContext(unitName = "otherPU")
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

Service1: 服务1:

@Service
@Transactional(readOnly = true)
public class MyService extends InheritedDao<MyModel> {
    public MyService() {
        setClazz(MyModel.class);
    }
}

Service2: 服务2:

@Service
@Transactional(readOnly = true)
public class OtherService extends OtherInheritedDao<MyModel> {
    public OtherService() {
        //same model as used in MyService
        setClazz(MyModel.class);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM