EJB 3 动态数据源的解决方案
程序员文章站
2022-05-28 12:23:44
...
项目碰到一个这样的需求:数据库划分为公共库、历史库、会员库和运行库。运行库可能有多个,但它们的表及表结构完全一致。一个运行库里存放着一个或多个分公司的数据。系统根据用户所属的分公司操作对应的运行库。(应用服务器是jboss 7)
方案如下:
首先,persistence.xml先配置一个模板运行库的部署单元, 这个部署单元对应的数据库必须存在。如
接下来,我们注入默认的EntityManager,我们的目标是获取默认的EntityManagerFactory,以它为模板,最终构造出我们需要的EntityManagerFactory。
接下来,开始构造
注:EntityManagerFactory是重量级对象,示例代码没有考虑重用,实际应该重用
方案如下:
首先,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是重量级对象,示例代码没有考虑重用,实际应该重用
上一篇: 解决方案:动态添加数据库字段
下一篇: 添加ppa源时出现错误解决方案