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

项目碰到一个这样的需求:数据库划分为公共库、历史库、会员库和运行库。运行库可能有多个,但它们的表及表结构完全一致。一个运行库里存放着一个或多个分公司的数据。系统根据用户所属的分公司操作对应的运行库。(应用服务器是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是重量级对象,示例代码没有考虑重用,实际应该重用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值