如果您使用的是bean managed transaction
,那麼使用CDI
來管理這種實體管理器工廠資源變得更加容易。
首先創建一個數據源上下文註釋。
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, PARAMETER, FIELD, METHOD})
public @interface Datasource {
/**
* This may be the database url or whatever.
*/
@Nonbinding
String value() default "";
}
@SuppressWarnings("AnnotationAsSuperInterface")
public class DatasourceLiteral extends AnnotationLiteral<Datasource> implements Datasource {
private static final long serialVersionUID = 7485753390480718735L;
private final String dbName;
public DatasourceLiteral(final String dbName) {
this.dbName = dbName;
}
@Override
public String value() {
return dbName;
}
}
@ApplicationScoped
public class EntityManagerFactoryProvider {
@Produces
@Datasource
@ApplicationScoped
public EntityManagerFactory entityManagerFactory(final InjectionPoint ip) {
final Annotated annotated = ip.getAnnotated();
final Datasource datasource = annotated.getAnnotation(Datasource.class);
/**
* Add relevant jpa properties
*/
final Map<String, String> jpaProperties = new HashMap<>();
/**
* The main point is here.
*/
jpaProperties.put("javax.persistence.jdbc.url", datasource.value());
return Persistence.createEntityManagerFactory("persistence-unit-jpa", jpaProperties);
}
public void dispose(@Disposes @Datasource final EntityManagerFactory emf) {
emf.close();
}
}
@ApplicationScoped
public class ExampleUserDatasource {
@Any
@Inject
private Instance<EntityManagerFactory> entityManagerFactories;
public void doSomething(final String user) {
final UserInfo userInfo = authenticationService.getUser(user);
final Datasource datasource = new DatasourceLiteral(userInfo.getDatasource());
final EntityManagerFactory entityManagerFactory = entityManagerFactories.select(datasource).get();
/**
* You could also actually inject this.
* Do whatever you want with it inside a transaction and close it too.
*/
final EntityManager entityManager = entityManagerFactory.createEntityManager();
}
}
一些代碼可能有助於重新驗證您的問題。 – FieryCat
在部署時(甚至在開發時)固定和已知數據庫集? –
不,它的動態@NikosParaskevopoulos –