使用 JPARepository 或 CRUDRepository 休眠(没有 Spring)

Hibernate with JPARepository or CRUDRepository (without Spring)

我有很多 classes:

DAO 用户:

public interface UserDao {

    User findById(int id);

    void save(User user);

    void update(User user);

    void delete(User user);

    List<User> findAll();
}

DaoImpl 用户:

public class UserDaoImpl implements UserDao {

    @Override
    public User findById(int id) {
    ...
        return user;
    }

    @Override
    public void save(User user) {
    ...
    }

    @Override
    public void update(User user) {
    ...
    }

    @Override
    public void delete(User user) {
    ...
    }

    @Override
    public List<User> findAll() {
    ...
    return users;
    }
}

VpnDao

public interface VpnDao {

    Vpn findById(byte id);

    void save(Vpn vpn);

    void update(Vpn vpn);

    void delete(Vpn vpn);

    List<Vpn> findAll();
}

VpnDaoImpl

public class VpnDaoImpl implements VpnDao {

    @Override
    public Vpn findById(byte id) {
    ...
        return vpn;
    }

    @Override
    public void save(Vpn vpn) {
    ...
    }

    @Override
    public void update(Vpn vpn) {
    ...
    }

    @Override
    public void delete(Vpn vpn) {
    ...
    }

    @Override
    public List<Vpn> findAll() {
    ...
        return vpnList;
    }
}

和大约 20 个具有相同 CRUD 方法的相似 classes。 我创建了 RepositoryDAO class:

@Log4j2
public class RepositoryDAO {

    public static void save(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.save(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

    public static void update(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.update(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

    public static void delete(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.delete(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

}

并在其中实现了重复的方法。

我不喜欢这个解决方案:(

我无法将所有重复的方法都带到 RepositoryDAO class

UserDaoImpl class 现在是:

public class UserDaoImpl implements UserDao {

    @Override
    public User findById(int id) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        User user = session.get(User.class, id);
        session.close();
        return user;
    }

    @Override
    public void save(User user) {
        RepositoryDAO.save(user);
    }

    @Override
    public void update(User user) {
        RepositoryDAO.update(user);
    }

    @Override
    public void delete(User user) {
        RepositoryDAO.delete(user);
    }

    @Override
    public List<User> findAll() {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        List<User> users = session.createQuery("From User", User.class).list();
        session.close();
        return users;
    }
}

我知道Spring中有一个JpaRepository或CrudRepository。 但是我们的项目没有使用Spring.

请告诉我如何在没有 Spring(仅 Hibernate)的情况下做类似于 JpaRepository 或 CrudRepository 的事情?

谢谢你。

我添加class RepositoryCRUD:

@Log4j2
public abstract class RepositoryCRUD {

    static <T> T findById(Class<T> type, Object id) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        T t = session.get(type, (Serializable) id);
        session.close();
        return t;
    }

    public static <T> List<T> findAll(Class<T> type) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        List<T> authorizationHistoryList = session.createQuery("From " + type.getName(), type).list();
        session.close();
        return authorizationHistoryList;
    }

    public static void save(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.save(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

    public static void update(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.update(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

    public static void delete(Object obj) {
        Transaction transaction = null;
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){
            transaction = session.beginTransaction();
            session.delete(obj);
            transaction.commit();
        } catch (Exception x) {
            log.error(x);
            if (transaction != null) transaction.rollback();
        }
    }

}

我的 class VpnDaoImpl 现在:

public class VpnDaoImpl implements VpnDao {

    @Override
    public Vpn findById(byte id) {
        return RepositoryCRUD.findById(Vpn.class, id);
    }

    @Override
    public void save(Vpn vpn) {
        RepositoryCRUD.save(vpn);
    }

    @Override
    public void update(Vpn vpn) {
        RepositoryCRUD.update(vpn);
    }

    @Override
    public void delete(Vpn vpn) {
        RepositoryCRUD.delete(vpn);
    }

    @Override
    public List<Vpn> findAll() {
        return RepositoryCRUD.findAll(Vpn.class);
    }

}

您可以使用默认行为实现 Dao 模式,在自定义 Dao 中扩展默认行为。

有一个GenericDao.java

import java.io.Serializable;

public interface GenericDao<T extends Serializable, Id extends Serializable> {
    T findById(Id id);

    T save(T entity);
}

在 GenericDaoImpl 中有一个默认实现

package org.elephant.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

public abstract class GenericDaoImpl<T extends Serializable, Id extends Serializable> implements GenericDao<T, Id> {
    private final SessionFactory sessionFactory;
    private final Class<T> persistentClass;

public GenericDaoImpl(SessionFactory sessionFactory) {
    this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    this.sessionFactory = sessionFactory;
}

@Override
public T findById(Id id) {
    Session session = sessionFactory.getCurrentSession();
    return session.find(persistentClass, id);
}

@Override
public T save(T entity) {
    Session session = sessionFactory.getCurrentSession();
    Serializable savedEntity = session.save(entity);
    return persistentClass.cast(savedEntity);
}

}

具体实现可以这样。 VpnDao 将具有继承自 GenericDaoImpl 的默认方法。如果需要任何定制,override/implement 它在 VanDao.java

import org.hibernate.SessionFactory;

public class VpnDao implements GenericDaoImpl<Vpn, Long>{
    public VpnDao(SessionFactory sessionFactory) {
        super(sessionFactory);
    }
}