欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EJB 3 动态数据源的解决方案

程序员文章站 2022-05-28 12:23:44
...
项目碰到一个这样的需求:数据库划分为公共库、历史库、会员库和运行库。运行库可能有多个,但它们的表及表结构完全一致。一个运行库里存放着一个或多个分公司的数据。系统根据用户所属的分公司操作对应的运行库。(应用服务器是jboss 7)
方案如下:
首先,persistence.xml先配置一个模板运行库的部署单元, 这个部署单元对应的数据库必须存在。如

<persistence-unit name="XXX_RUNTIME_DS" transaction-type="JTA">
<jta-data-source>java:/XXX_RUNTIME_DS_001</jta-data-source>
...
</persistence-unit>

接下来,我们注入默认的EntityManager,我们的目标是获取默认的EntityManagerFactory,以它为模板,最终构造出我们需要的EntityManagerFactory。

@PersistenceContext(unitName = "XXX_RUNTIME_DS")
private EntityManager em;

接下来,开始构造

protected EntityManager getEntityManager() {
String db = ...;//用于判断运行库
if(db.equal(...)){//返回默认的运行库
return em;
}
//构造EntityManagerFactory
String dbStuffix = db.substring(db.indexOf(DBConstants.DB_RUNTIME_PREV) + DBConstants.DB_RUNTIME_PREV.length());//这里的值是部署单元中JNDI的_001,我们把JNDI构造成类似于java:/XXX_RUNTIME_DS_002/java:/XXX_RUNTIME_DS__003,其他类似
//覆盖某些属性
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.infinispan.JndiInfinispanRegionFactory");
properties.put("hibernate.cache.infinispan.cachemanager", "java:jboss/infinispan/hibernate");
properties.put("javax.persistence.jtaDataSource", DBConstants.DS_JNDI_PREV + dbStuffix);
properties.put("hibernate.session_factory_name", em.getEntityManagerFactory().getProperties().get("hibernate.session_factory_name") + dbStuffix);
properties.put("hibernate.cache.region_prefix", em.getEntityManagerFactory().getProperties().get("hibernate.cache.region_prefix") + dbStuffix);
properties.put("hibernate.ejb.entitymanager_factory_name", em.getEntityManagerFactory().getProperties().get("hibernate.ejb.entitymanager_factory_name") + dbStuffix);
//创建EntityManagerFactory
EntityManagerFactory emf = Persistence.createEntityManagerFactory("XXX_RUNTIME_DS", properties);
String puScopedName = emf.getProperties().get("hibernate.ejb.entitymanager_factory_name").toString();
//创建EntityManager
EntityManager entityManager;
boolean isInTx;
isInTx = TransactionUtil.isInTx();
if (isInTx) {
entityManager = TransactionUtil.getOrCreateTransactionScopedEntityManager(emf, puScopedName, emf.getProperties());
} else {
entityManager = NonTxEmCloser.get(puScopedName);
if (entityManager == null) {
entityManager = EntityManagerUtil.createEntityManager(emf, null);
NonTxEmCloser.add(puScopedName, entityManager);
}
}
return entityManager;
}

注:EntityManagerFactory是重量级对象,示例代码没有考虑重用,实际应该重用