jpa - 如何将我的 DAO Bean 从 EJB 更改为纯 CDI?

标签 jpa jakarta-ee cdi

我想在新项目中重用 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/

相关文章:

java - 使用 JPA 返回两个结果集

java - 如何从 Spring Security 扩展用户类并使用 JPA 创建表

mysql - JPA 调用很长 - 如何检查问题是来自 jpa 还是来自 mysql

Hibernate/JDBC 为 Informix 数据库生成错误的 SQL

java - Web App 中使用的 JAR 的 MANIFEST.MF 文件?

java - 使用 Java 将文档上传到共享点的 API

java - CDI 拦截器与 CDI 事件

jakarta-ee - 将@SessionScoped CDI Bean 注入(inject)@Stateless EJB

java - CDI 生产商利益

java - 当结果为列表时,JPA @OneToMany 不起作用