java - 在混合租赁上下文中生成 EntityManager

标签 java jpa jakarta-ee cdi

我有这样的要求,每个客户都必须将他的数据单独存储在一个单独的数据库中。

我想实现如下结构:

  1. 全局微服务处理身份验证,并提供有关存储客户端数据的数据库的信息。
  2. 其他微服务在收到请求时查询身份验证服务以了解客户端数据库信息,然后才生成实体管理器。

我正在努力正确管理 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/

相关文章:

构造函数中的 Java Enum 无法解析为变量

java - 尝试使用tomcat在servlet中加载dll时出现NoClassDefFoundError

java - 使用 EJB 注入(inject)用户实体

java - 在序列化之前从 session 中删除属性

java - Tomcat错误: A child container failed during start

java - 如何在单击时更改按钮背景

java - 如何在 Hibernate/JPA 中实现 "optional"关系?

java - 使用 JPA 在运行时更改表名称

java - QueryDSL:QueryDSL 2.9.0 中 ConstructorExpression 和 CaseBuilder 的 JPA 示例

java - 停止在 ear 文件中部署重复 jar 的策略