简体   繁体   English

管理多个数据库连接

[英]Managing Multiple Database Connections

I've been struggling with this problem for days, 我已经为这个问题苦苦挣扎了好几天了,

Here is the scenario: I have several databases, one for each of my customers, all of them with the same structure(same tables and columns), so my application needs to decide at runtime with which one it needs to connect. 这是一个场景:我有几个数据库,每个客户一个数据库,所有数据库都具有相同的结构(相同的表和列),因此我的应用程序需要在运行时确定需要连接的数据库。 I'm using JPA2, EclipseLink and EJB3. 我正在使用JPA2,EclipseLink和EJB3。

My first attempt was to implement a custom EntityManager with all the logic to performs the operations on the right database, then I configured this EntityManager as an Stateless EBJ in order to make it possible to inject it with the @EBJ annotation (as described at this link: http://www.hostettler.net/blog/2012/11/20/multi-tenancy/ ). 我的第一个尝试是用所有逻辑来实现自定义EntityManager,以便在正确的数据库上执行操作,然后我将此EntityManager配置为无状态EBJ,以便可以使用@EBJ注释注入它(如此处所述)链接: http//www.hostettler.net/blog/2012/11/20/multi-tenancy/ )。 I coundn't make it work because it was throwing an exception when trying to inject the EntityManager. 我无法使其正常工作,因为它在尝试注入EntityManager时抛出异常。

So I decided to try something else, I've created EntityManagerFactory and I passed the JTA_DATASOURCE to it(after decide at runtime which one to use), so it could connect to the right database. 因此,我决定尝试其他方法,创建了EntityManagerFactory,并将JTA_DATASOURCE传递给它(在运行时决定使用哪个),以便它可以连接到正确的数据库。

Here is the code: 这是代码:

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class TestEntDAO {

    private EntityManager em;
    private EntityManagerFactory emf;

    @PostConstruct
    public void init() {
        em = getEntityManager();
    }

    public EntityManager getEntityManager() {
        Map props = new HashMap();
        props.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA");
        props.put(PersistenceUnitProperties.JTA_DATASOURCE, dataSourceName());
        emf = Persistence.createEntityManagerFactory("testePU", props);
        em = emf.createEntityManager();
        return em;
    }

    public String dataSourceName(){
        if(someCondition){
            return "db1";
        }else{
            return "db2";
        }
    }
}

This worked perfectly, the only problem is that the transaction is not managed by the container, so I had to explicitly mark the transaction's boundaries(call begin() and commit()). 这样做很完美,唯一的问题是事务不是由容器管理的,因此我必须明确标记事务的边界(调用begin()和commit())。 I could just use the @PersistenceContext annotation to make it work, but then I wouldn't have the EntityManagerFactory to pass the datasource. 我可以只使用@PersistenceContext批注使其工作,但是那样我就没有EntityManagerFactory来传递数据源。

Does anyone know of a way to use the Container-Managed Transactions(CMT) and still be able to pass the datasource? 有谁知道使用容器管理事务(CMT)的方法,并且仍然能够传递数据源?

Maybe try to define 3 Data sources and 3 Persistence units. 也许尝试定义3个数据源和3个持久性单位。

<persistence-unit name="PU1">
  <jta-data-source>jdbc/DS1</jta-data-source>
  ...
</persistence-unit>
<persistence-unit name="PU2">
  <jta-data-source>jdbc/DS2</jta-data-source>
  ...
</persistence-unit>
<persistence-unit name="PU3">
  <jta-data-source>jdbc/DS3</jta-data-source>
  ...
</persistence-unit>

And inject Entity manager from whatever Persistence unit you want. 然后从所需的任何持久性单元中注入实体管理器。

@PersistenceContext(unitName = "PU2")
EntityManager em;

This should work, although I didn't test it. 尽管我没有测试,但这应该可以工作。

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

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