我想在新项目中重用 AbstractDAO,但这次我不想使用 EJB 注释 - 仅使用 CDI 注释。
到目前为止,我一直这样使用它:
public abstract class AbstractDAO<T> {
@PersistenceContext(unitName = "myUnit")
private EntityManager entityManager;
private Class<T> entityClass;
public AbstractDAO(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected EntityManager getEntityManager() {
return entityManager;
}
public void save(T entity) {
entityManager.persist(entity);
}
public void update(T entity) {
entityManager.merge(entity);
}
public void remove(T entity) {
entityManager.remove(entityManager.merge(entity));
}
public T findById(Object id) {
return entityManager.find(entityClass, id);
}
public List<T> findBy(String attrName, Object attrValue) {
// Impl here
}
// [...] Many more search methods
}
我一直在为每个实体创建一个 DAO,例如:
@Stateless
public class UserDAO extends AbstractDAO<User> {
public UserDAO() {
super(User.class);
}
public User findByUsername(String username) {
if (username != null) {
return super.findOneBy("username", username.toLowerCase());
}
return null;
}
}
现在我想摆脱 @Stateless 注释。但仅仅将其替换为 @RequestScoped 是行不通的,因为 JSR-346 要求不带参数的非私有(private)构造函数。
如何将我的 DAO 重构为纯 CDI ?
最佳答案
这里有两个问题:CDI bean 默认情况下不支持事务 - 与 EJB 不同,因此如果您想进行保存/更新,则必须使用 @Transactional
限定符...
其次,您的无参数构造函数:您只需将实体类传递给抽象类,即使您也将其指定为通用参数。您可以像这样推断实际的类:
public class AbstractDAO<T> {
private transient Class<T> entityClass;
@SuppressWarnings("unchecked")
public AbstractDAO() {
Type generSuperCls = getClass().getGenericSuperclass();
if (generSuperCls instanceof Class) {
generSuperCls = ((Class<?>) generSuperCls).getGenericSuperclass();
}
ParameterizedType parameterizedType = (ParameterizedType) generSuperCls;
Type type = parameterizedType.getActualTypeArguments()[0];
if (type instanceof Class) {
this.entityClass = (Class<T>) type;
} else if (type instanceof ParameterizedType) {
this.entityClass = (Class<T>) ((ParameterizedType) type).getRawType();
}
}
@PersistenceContext
private EntityManager em;
public T getById(Object id) throws ServiceException {
return getEm().find(entityClass, id);
}
// other methods follow
}
顺便说一句,为什么要摆脱 EJB? Benchmarks show使用池化 slsb 可以获得比 cdi 更好的性能,并且它们结合得很好(每个 EJB bean 也是 jee 容器中的 CDI bean)。
关于jpa - 如何将我的 DAO Bean 从 EJB 更改为纯 CDI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44268124/