java是否可以在运行时动态实例化DAO类?
所以我四处看了看,但仍然找不到任何能帮助我的东西。这是我的代码:
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());
}
}
如您所见,我将返回使用“tablename”找到的相应DAO的实例。我需要这个方法,因为我可以通过一些参数知道在运行时查询哪个表。唯一的问题是,当我调用'findById'方法时,它只会给我一个空指针异常,因为该dao的EntityManager是空的
现在。。。EntityManager工作正常。下面是调用该方法的类
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)));
}
}
因此,在这里,与注入的DAO相关的第一个“findById”工作正常,而另一个DAO无论如何都将为任何调用的方法返回空指针,因为实体管理器为空。我想这是因为它不是注入bean,有没有办法解决这个问题并修复实体管理器为null的问题
编辑:我忘了提到我在做这件事时没有使用Spring,只使用普通的CDI。无论如何,分享评论中提到的DAO类结构可能会很有用:
这是ExtendedDAO,它扩展了包含一些默认查询方法的BaseDAO:
@Slf4j 公共抽象类ExtendedBaseDAO<;T扩展BaseEntity,ID扩展Serializable>;扩展BaseDao<;T、 ID>;{
@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;
}
}
任何DAO类都会扩展这个类,因此可以访问EntityManager。事实上,对于服务方法中的注入DAO来说,这是非常好的
# 1 楼答案
因为您控制着DAO类,所以我认为将字符串动态转换为bean的最简单解决方案是使用带有绑定成员的CDI限定符(参见CDI 2.0规范第5.2.6节)
所以你已经有了:
使用绑定成员定义限定符批注:
将其添加到你的bean中:
创建实用工具注释文字:
像这样理解:
Here是一篇描述这一点的好文章
注意动态创建)
@Dependent
作用域bean,请参见this!!!TL;DR:最好为DAO定义一个明确的正常范围(例如^{