Java 将CDI限定符传输到注入字段

Java 将CDI限定符传输到注入字段,java,jakarta-ee,cdi,java-ee-7,Java,Jakarta Ee,Cdi,Java Ee 7,我正在Wildfly 8.2容器中开发一个JavaEE7应用程序,该容器包含两个数据源中存在的一些实体。例如: 我有一个带有设置的jar实体: @Entity public class Setting { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @NotNull private String name; private String value;

我正在Wildfly 8.2容器中开发一个JavaEE7应用程序,该容器包含两个数据源中存在的一些实体。例如:

我有一个带有
设置的jar
实体:

@Entity
public class Setting {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    private String name;
    private String value;

    getters/setters...
}
还有一个bean,它有两种方法通过条件查询从数据库检索和保存该实体:

@Stateless
public class SettingRepository {
    @Inject
    private Logger logger;

    @Inject
    private EntityManager entityManager;

    public Setting findByName(@NotNull String name) {
        logger.trace("Getting setting by name: name=" + name);
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Setting> cq = cb.createQuery(Setting.class);
        Root<Setting> table = cq.from(Setting.class);
        cq.where(cb.equal(table.get(Setting_.name), name));

        TypedQuery<Setting> query = entityManager.createQuery(cq);
        List<Setting> results = query.getResultList();
        Setting setting = null;

        if (results.size() > 0)
            setting = results.get(0);

        logger.trace("Got setting: " + setting);
        return setting;
    }

    ...
}
有没有办法在注入点配置SettingRepository并告诉它使用特定的实体管理器(
@DataSource1
@DataSource2
)?

与此类似:

@Inject @DataSource1
private SettingRepository settingRepository;
对!

事实上,就生产者方法和限定符而言,您已经完成了所有艰苦的工作:-)您需要做的就是在注入的EntityManager实例上使用限定符(@DataSource1等)

@Inject @DataSource1
private EntityManager entityManager;

这将确保连接到持久性单元“pu1”的JPA实体管理器由容器注入。

我选择的路径是:

我创建了一个限定符

@Qualifier
@Retention(RUNTIME)
@Target({ METHOD, FIELD, PARAMETER })
public @interface DataSource {
    @Nonbinding DataSourceName value() default DataSourceName.D1;
}
注意
@Nonbinding
注释,它告诉container在注释producer方法(尤其是这个方法,因为我可以实现泛型producer,稍后会详细介绍)或注入点时不必指定此参数

DataSourceName
enumeration,它只列出所有数据源:

public enum DataSourceName {
    D1, D2
}
我还更改了
SettingRepository
实现,并添加了一个公共初始化方法

@Dependent
public class SettingRepository {
    @Inject
    private Logger logger;

    private EntityManager entityManager;

    public void initialize(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    ...
}
请注意,
EntityManager
不再由容器注入

当我不想注入
设置存储库
时,我只是用以下限定符来修饰它:

@Inject @DataSource(DataSourceName.D1)
private SettingRepository settingRepository;
我现在只需要为
设置存储库定义一个生产者

@Stateless
public class TestResourcesForSettings {
    @PersistenceContext(unitName = "pu1")
    private EntityManager entityManager1;

    @PersistenceContext(unitName = "pu2")
    private EntityManager entityManager2;

    @Inject
    private SettingRepository settingRepository;

    @Produces @DataSource
    public SettingRepository produceSettingRepository(InjectionPoint ip) {
        DataSource annotation = ip.getAnnotated().getAnnotation(DataSource.class);

        if (annotation.value() == DataSourceName.D1)
            settingRepository.initialize(entityManager1);
        else if (annotation.value() == DataSourceName.D2)
            settingRepository.initialize(entityManager2);

        return settingRepository;
    }

瞧,我可以使用两个数据源和一个存储库实现(注意:数据源必须是XA)如果有人发现此选择有任何问题,请告诉我。

谢谢,但我第一次知道我需要的数据源是在
设置还原
注入点,而不是
实体管理器
注入点。所以我想知道是否有一种方法可以将限定符从父注入点(
SettingsRepository
)转移到子注入点(
EntityManager
),或者在每个方法上使用参数更好。
@Stateless
public class TestResourcesForSettings {
    @PersistenceContext(unitName = "pu1")
    private EntityManager entityManager1;

    @PersistenceContext(unitName = "pu2")
    private EntityManager entityManager2;

    @Inject
    private SettingRepository settingRepository;

    @Produces @DataSource
    public SettingRepository produceSettingRepository(InjectionPoint ip) {
        DataSource annotation = ip.getAnnotated().getAnnotation(DataSource.class);

        if (annotation.value() == DataSourceName.D1)
            settingRepository.initialize(entityManager1);
        else if (annotation.value() == DataSourceName.D2)
            settingRepository.initialize(entityManager2);

        return settingRepository;
    }