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:
- Create a
CRUDBean
constructor which takes the entity class as an argument. - Add a parameter to
size()
which takes the entity class as an argument. - Use the same trick as in the current
GenericDAO
constructor to get it, but withgetGenericInterfaces()
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);
}
精彩评论