Java 可以在运行时动态实例化DAO类吗?
所以我四处找了一下,但仍然找不到任何能帮助我的东西。这是我的代码:Java 可以在运行时动态实例化DAO类吗?,java,cdi,entitymanager,reflections,Java,Cdi,Entitymanager,Reflections,所以我四处找了一下,但仍然找不到任何能帮助我的东西。这是我的代码: public ExtendedBaseDAO getCorrespondingDAO(String tableName) throws DAOException { log.info("BaseService.getCorrespondingDAO(...): Getting DAO correspondant to table with name " + tableName
public ExtendedBaseDAO getCorrespondingDAO(String tableName) throws DAOException {
log.info("BaseService.getCorrespondingDAO(...): Getting DAO correspondant to table with name " + tableName
+ "...");
try {
Optional<EntityType<?>> entityFound = entityManager.getMetamodel().getEntities().stream()
.filter(entity -> ((Table) entity.getJavaType().getAnnotation(Table.class)).name().equalsIgnoreCase(tableName)).findFirst();
log.info("Found entity with name " + entityFound.get().getJavaType().getSimpleName() + " mapped to " + tableName);
Reflections reflections = new Reflections("eu.unicredit.fit.fit_core.dao");
Optional<Class<? extends ExtendedBaseDAO>> daoClassFound = reflections.getSubTypesOf(ExtendedBaseDAO.class)
.stream().filter(daoClass -> daoClass.getSimpleName().replaceAll("DAO", "")
.equals(entityFound.get().getJavaType().getSimpleName()))
.findFirst();
log.info("The correspondant DAO found is " + daoClassFound.get().getSimpleName() + ". Instantiating it...");
return daoClassFound.get().getConstructor().newInstance();
} catch (Exception e) {
throw new DAOException("It was not possible to find the DAO associated with the table " + tableName
+ "! Error: " + e.getLocalizedMessage());
}
}
public ExtendedBaseDAO getCorrespondingDAO(String tableName)引发异常{
log.info(“BaseService.getCorrespondingDAO(…):将DAO对应到名为“+tableName”的表
+ "...");
试一试{
可选因为您控制着DAO类,所以我认为将字符串动态转换为bean的最简单解决方案是使用带有绑定成员的CDI限定符(请参见CDI 2.0规范第5.2.6节)
因此,您已经:
公共抽象类ExtendedBaseDAO扩展BaseDao{{
...
}
@适用范围
公共类WizardFieldConfigDAO扩展了ExtendedBaseDAO{
...
}
@适用范围
公共类OtherDAO扩展了ExtendedBaseDAO{
...
}
使用绑定成员定义限定符批注:
@限定符
@保留(运行时)
@目标({方法,字段,参数,类型})
公共@interface MyDao{
字符串tableName();
}
将其添加到您的bean中:
@MyDao(tableName=“其他”)
@适用范围
公共类WizardFieldConfigDAO扩展了ExtendedBaseDAO{…}
@MyDao(tableName=“其他”)
@适用范围
公共类OtherDAO扩展了ExtendedBaseDAO{…}
创建实用工具注释文字:
import javax.enterprise.util.AnnotationLiteral;
公共类MyDaoQualifier扩展AnnotationLiteral实现MyDao{
私有字符串表名;
公共MyDaoQualifier(字符串表名){
this.tableName=tableName;
}
@凌驾
公共字符串tableName(){
返回表名;
}
}
像这样理解:
@Inject@Any
私有实例呃,注入ApplicationContext
并从那里获取bean?当然你不能对它使用反射。Spring怎么知道如何正确初始化它。你控制DAO类吗?你能在它们上添加CDI限定符注释吗?如果能,你可以使用CDI的实例
动态检索它们ant要(或必须)使用反射,并且您知道DAO只依赖于EntityManager
,您可以添加构造函数(或setter)并在反射构造上调用它。如果您可以添加一个方法ExtendedBaseDAO.setEntityManager
,它将极大地简化事情。@NikosParaskevopoulos是的,我控制着DAO类。我如何动态检索它们?您能回答堆栈问题吗?这样,如果它确实有效,我会将其标记为已接受。还有seco第二个建议,我想了一下,但它在结构上不是错了吗?我是说ofc我可以在包含getCorrespondingDAO的类中注入EntityManager,然后将该实体管理器传递给setter。这是个好主意吗?@Kayaman很遗憾,我没有使用spring。我理解这种混乱,因此添加了一个编辑非常感谢。刚刚测试过它,它非常有效。CDI实际上有一些很好的隐藏功能,我想,在网上找不到。
public class WizardFieldConfigService extends BaseService {
@Inject
private WizardFieldConfigDAO wizardFieldConfigDAO;
/**
* Retrieves the field data from the specific table requested for. To specify
* the table use the fieldDataRequest.
*
* @param fieldDataRequest The DTO to be used as input
* @return a {@link FieldDataResponseDTO} object with a map containing the
* requested values
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public FieldDataResponseDTO getFieldData(FieldDataRequestDTO fieldDataRequest) {
log.info("WizardFieldConfigService.getFieldData(...): Retrieving field data for field with id "
+ fieldDataRequest.getFieldID() + "...");
WizardFieldConfig fieldBaseData = wizardFieldConfigDAO.findByID((long)fieldDataRequest.getFieldID());
log.info("Found field data: " + fieldBaseData.toString());
List<BaseEntity> response = getCorrespondingDAO(fieldBaseData.getDomainName())
.findWithConditions(fieldDataRequest.getConditions());
return new FieldDataResponseDTO().setPlaceHolder(fieldBaseData.getPlaceholder())
.setLabel(fieldBaseData.getFieldName()).setRegex(fieldBaseData.getRegex())
.setValueList((Map<? extends Serializable, String>) response.stream()
.collect(Collectors.toMap(BaseEntity::getId, BaseEntity::getDescription)));
}
}
@PersistenceContext(unitName = "fit-core-em")
private EntityManager em;
protected ExtendedBaseDAO(Class<T> type) {
super(type);
}
public List<T> findWithConditions(List<ConditionDTO> conditions) {
//...
}
@Override
protected EntityManager getEntityManager() {
return this.em;
}