2017-05-30 21 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