简体   繁体   English

为JPA创建一个可以继承的通用DAO

[英]Creating a generic DAO for JPA that I can inherit from

I am trying to create a repository class that I can inherit from to get basic CRUD functionality from. 我正在尝试创建一个我可以继承的存储库类,以从中获取基本的CRUD功能。 The EntityManager.find(..) needs a Class argument. EntityManager.find(..)需要一个Class参数。 However, you can't pass T to it (By some reason I don't understand yet...type erasure). 但是,你不能把T传递给它(由于某种原因我还不明白......类型擦除)。 So I found the method that returns the entity class and added it from another question I saw. 所以我找到了返回实体类的方法,并从我看到的另一个问题中添加了它。 First of all, how does it work and second would it have much impact on performace? 首先,它是如何工作的,第二,它会对性能产生多大影响? I see it use reflection. 我看到它使用反射。

@Stateless
public abstract class AbstractSqlRepository<T> implements Repository<T> {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void create(T entity) {
        entityManager.persist(entity);
    }

    @Override
    public T find(int id) {
        return entityManager.find(getEntityClass(), id);
    }

    @Override
    public T update(T entity) {
        return entityManager.merge(entity);
    }

    @Override
    public void remove(T entity) {
        entityManager.remove(entity);
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public Class<T> getEntityClass() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();

        return (Class<T>) genericSuperclass.getActualTypeArguments()[0];
    }
}

New approach: 新的方法:

@Stateless
public abstract class AbstractSqlRepository<T> implements Repository<T> {

    @PersistenceContext
    private EntityManager entityManager;
    private Class<T> clazz;

    public AbstractSqlRepository(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public void create(T entity) {
        entityManager.persist(entity);
    }

    @Override
    public T find(int id) {
        return entityManager.find(clazz, id);
    }

    @Override
    public T update(T entity) {
        return entityManager.merge(entity);
    }

    @Override
    public void remove(T entity) {
        entityManager.remove(entity);
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }
}

and

public class QuestionSqlRepository extends AbstractSqlRepository implements QuestionRepository { public class QuestionSqlRepository extends AbstractSqlRepository实现QuestionRepository {

public QuestionSqlRepository() {
    super(Question.class);
}

} }

Is this a bad approach? 这是一个糟糕的方法吗?

It is stated that reflection will add overhead but you don't have to get the Class of the object every time in my opinion. 据说反射会增加开销,但在我看来,你不必每次都得到对象的Class。

Just find it the first time and check for null afterwards, this adds very little overhead compared to call a super class method. 只是第一次找到它并在之后检查null,与调用超类方法相比,这增加了很少的开销。

The only argument against the constructor parameter is that your class won't be a POJO. 对构造函数参数的唯一参数是您的类不是POJO。

Here is the sample code: 以下是示例代码:

@SuppressWarnings("unchecked")
public class HibernateBaseDao<T, Pk extends Serializable> implements Dao<Pk, T> {

    // ...
    private Class<T> type;

    // ...

    public Class<T> getType() {

        if (this.type == null) {

            ParameterizedType parameterizedType = (ParameterizedType) (this
                    .getClass().getGenericSuperclass());

            while (!(parameterizedType instanceof ParameterizedType)) {
                parameterizedType = (ParameterizedType) parameterizedType
                        .getClass().getGenericSuperclass();
            }

            this.type = (Class<T>) parameterizedType.getActualTypeArguments()[0];

        }

        return this.type;
    }

    @Override
    public T load(Pk id) {

        return (T) this.sessionFactory.getCurrentSession().load(this.getType(),
                id);
    }

    @Override
    public T get(Pk id) {
        return (T) this.sessionFactory.getCurrentSession().get(this.getType(),
                id);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM