开发者

Is it possible with generics?

开发者 https://www.devze.com 2023-04-04 17:41 出处:网络
I have class: public class GenericDAO<T, ID extends Serializable> { private final EntityManager em;

I have class:

public class GenericDAO<T, ID extends Serializable> {
private final EntityManager em;
private final Class<T> entityClass;
public GenericDAO(EntityManager em) {
    this.em = em;
    ParameterizedType genericSuperClass = (ParameterizedType) getClass().getGenericSuperclass();
    this.entityClass = (Class<T>) genericSuperClass.getActualTypeArguments()[0];
}
}

If I extend this class all works fine. Now I want to use this class directly (see code belove, CRUDBean is implementation of CRUDService) - it is necessary to rewrite constructor to get particular class.

@Remote(CRUDService.class)
@Stateless
public class CRUDBean<T extends EntityBase> implements CRUDService<T> {
@PersistenceContext
private EntityManager entityManager;

@Override
public long size(String whereClause, Map<Stri开发者_运维技巧ng, Object> whereParameters) {
    return new GenericDAO<T, Long>(entityManager).size(whereClause, whereParameters);
}
}

How to write such generics service?


Yes, you would need to create a separate constructor.

Your current constructor assumes that this is an instance of a subclass of GenericDAO, and it uses that fact to get the type parameter for you through getClass().getGenericSuperclass().getActualTypeArguments().

To use GenericDAO directly, you should create a GenericDAO constructor which takes the entity class (whatever type T really is) as an argument. Then provide the entity class in CRUDBean.size() or wherever you need to instantiate your GenericDAO.

If you don't have the actual class available in CRUDBean, have three choices:

  1. Create a CRUDBean constructor which takes the entity class as an argument.
  2. Add a parameter to size() which takes the entity class as an argument.
  3. Use the same trick as in the current GenericDAO constructor to get it, but with getGenericInterfaces() instead.


I would suggest using an explicit "type token", rather than reusing a class.


The usual, and easiest, way around this to pass an instance of the class to the constructor:

public GenericDAO(EntityManager em, Class<T> entityClass) {
    this.em = em;
    this.entityClass = entityClass;
}

Then call it like this:

public long size(String whereClause, Map<String, Object> whereParameters, Class<T> entityClass) {
    return new GenericDAO<T, Long>(entityManager, entityClass).size(whereClause, whereParameters);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消