2017-05-30 22 views
1

我想在一个新项目中重用我的AbstractDAO,但这次我不想使用EJB注释 - 只是CDI的如何将我的DAO Bean从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

我如何修改我的DAO到纯CDI一个?

+1

'UserDAO'有一个无参数的非私有构造函数。而'@ PersistenceContext'将在JEE环境*中用于CDI bean *。我没有得到正确的问题吗?你真的尝试过使用'UserDAO'' @ RequestScoped'吗?错误是什么? –

+0

只是好奇 - 你想通过这样做达到什么目的? –

+0

我发现CDI和EJB bean的混合让很多人感到困惑(至少在我的最后一个项目中)。另外,我读了这个:http://theelitegentleman.blogspot.de/2014/04/daos-as-ejbs-you-are-doing-it-wrong.html – Tim

回答

2

两个问题在这里:只有你:CDI bean不是事务感知默认-unlike 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)。

+0

我发现CDI和EJB bean的混合让很多人感到困惑(至少在我上一个项目中)。另外,我读了这个:http://theelitegentleman.blogspot.de/2014/04/daos-as-ejbs-you-are-doing-it-wrong.html。我不知道这个表现。我将尝试您的解决方案 – Tim

+1

如果您将DAO层与业务服务分开,那么您链接的帖子将反对混合业务和数据层,而事实并非如此。 EJB和CDI bean都是容器管理的组件,可以执行各种角色。在内部它们非常相似(如果你忽略了远程ejbs的遗留负担等),并且一些服务器甚至以通用的方式处理它们。每个问题总会有一个好的解决方案:)SLSB〜= @ pooled&@ Transactional CDI。但是你是对的,为你的团队做些有意义的事情,增加10%的额外性能并不值得开发者的失望。 – yntelectual