Это возможно! Я сделал это, и он работает под JBoss AS и WebSphere.
Я использую пользовательский поставщик сохраняемости, который расширяет org.hibernate.ejb.HibernatePersistence
(вам нужно изменить private static final
поле , чтобы установить имя поставщика сохраняемости на org.hibernate.ejb3.Ejb3Configuration.IMPLEMENTATION_NAME
: это своего рода черная магия, но работает). Убедитесь, что в ваших единицах постоянства persistence.xml
пользовательский поставщик установлен в теге <provider>
, а ваш пользовательский поставщик зарегистрирован в META-INF/services/javax.persistence.spi.PersistenceProvider
.
Мой провайдер переопределяет метод createContainerEntityManagerFactory(PersistenceUnitInfo,Map)
, называемый контейнером Java EE, как таковой (для источника данных JTA, но было бы легко сделать это и для источника данных не JTA):
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) {
// load the DataSource
String newDataSourceName = ...; // any name you want
DataSource ds = (DataSource)(new InitialContext().lookup(newDataSourceName));
// modify the datasource
try {
try {
// JBoss implementation (any maybe other Java EE vendors except IBM WebSphere)
Method m = info.getClass().getDeclaredMethod("setJtaDataSource", DataSource.class);
m.setAccessible(true);
m.invoke(info, ds);
} catch (NoSuchMethodException e) {
// method does not exist (WebSphere?) => try the WebSphere way
// set the datasource name
Method m = info.getClass().getDeclaredMethod("setJtaDataSource", String.class);
m.setAccessible(true);
m.invoke(info, newDataSourceName);
// do the lookup
Method m2 = info.getClass().getDeclaredMethod("lookupJtaDataSource", String.class);
m2.setAccessible(true);
m2.invoke(info);
}
} catch (Throwable e) {
throw new RuntimeException("could not change DataSource for "+info.getClass().getName());
}
// delegate the EMF creation
return new HibernatePersistence().createContainerEntityManaferFactory(info, map);
}
createEntityManagerFactory(String,Map)
также переопределяет, но намного проще:
@Override
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitInfo, Map map) {
// change the datasource name
String newDataSourceName = ...; // any name you want
if (map==null) map = new HashMap();
map.put(HibernatePersistence.JTA_DATASOURCE, newDataSourceName);
// delegate the EMF creation
return new HibernatePersistence().createEntityManaferFactory(persistenceUnitInfo, map);
}
Обратите внимание, что я написал здесь только основной код. На самом деле, мой поставщик персистентности имеет много других функций:
- проверьте, что источник данных запущен и работает
- установить менеджер транзакций для JBoss или WebSphere
- кэшировать EMF для уменьшения использования памяти
- перенастроить кэш плана запросов Hibernate для меньшего использования памяти
- зарегистрировать bean-компонент JMX (чтобы несколько EAR могли получить одно и то же имя единицы сохраняемости)