我有这样的要求,每个客户都必须将他的数据单独存储在一个单独的数据库中。
我想实现如下结构:
- 全局微服务处理身份验证,并提供有关存储客户端数据的数据库的信息。
- 其他微服务在收到请求时查询身份验证服务以了解客户端数据库信息,然后才生成实体管理器。
我正在努力正确管理 EntityManagerFactory
实例的状态。
我尝试将其存储在 WeakHashMap
中,但开始出现一些错误。就像一个简单的 findById
抛出异常。
我实际上是在使用 JEE,DeltaSpike 数据在 Payara 服务器上运行。
有人用过类似的堆栈吗?
最佳答案
如果您正在使用 bean 管理的事务
,那么使用 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();
}
}
关于java - 在混合租赁上下文中生成 EntityManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44396925/