休眠:CRUD 通用 DAO

2022-09-01 05:43:06

我的 Web 应用程序有很多服务表/实体,例如 、 、 等。payment_methodstax_codesprovince_codes

每次添加新实体时,我都必须编写一个 DAO。问题是,基本上,它们都是相同的,但唯一的区别是实体类本身

我知道Hibernate工具可以自动为我生成代码,但我现在不能使用它们(不要问为什么),所以我正在考虑一个通用DAO。有很多关于这方面的文献,但我不能把碎片放在一起,让它与春天一起工作。

我认为这都是关于泛型的,它将有四个基本方法:

  • listAll
  • saveOrUpdate
  • deleteById
  • getById

仅此而已。


问题:

不重新发明轮子的最佳实践是什么?难道还没有准备好使用的东西吗?


答案 1

这是我的

@Component
public class Dao{

    @Resource(name = "sessionFactory")
    private SessionFactory sessionFactory;

    public <T> T save(final T o){
      return (T) sessionFactory.getCurrentSession().save(o);
    }


    public void delete(final Object object){
      sessionFactory.getCurrentSession().delete(object);
    }

    /***/
    public <T> T get(final Class<T> type, final Long id){
      return (T) sessionFactory.getCurrentSession().get(type, id);
    }

    /***/
    public <T> T merge(final T o)   {
      return (T) sessionFactory.getCurrentSession().merge(o);
    }

    /***/
    public <T> void saveOrUpdate(final T o){
      sessionFactory.getCurrentSession().saveOrUpdate(o);
    }

    public <T> List<T> getAll(final Class<T> type) {
      final Session session = sessionFactory.getCurrentSession();
      final Criteria crit = session.createCriteria(type);
  return crit.list();
    }
// and so on, you shoudl get the idea

然后,您可以在服务层中像这样访问:

 @Autowired
    private Dao dao;

   @Transactional(readOnly = true)
    public List<MyEntity> getAll() {
      return dao.getAll(MyEntity.class);
    }

答案 2

Spring Data JPA是一个很棒的项目,可以为您生成DAO,甚至更多!你只需要创建一个接口(没有任何实现):

interface PaymentMethodsDao extends JpaRepository<PaymentMethods, Integer> {}

这个接口(通过继承的JpaRepository)将自动为您提供:

PaymentMethod save(PaymentMethod entity);
Iterable<PaymentMethod> save(Iterable<? extends PaymentMethod> entities);
PaymentMethod findOne(Integer id);
boolean exists(Integer id);
Iterable<PaymentMethod> findAll();
long count();
void delete(Integer id);
void delete(PaymentMethod entity);
void delete(Iterable<? extends PaymentMethod> entities);
void deleteAll();
Iterable<PaymentMethod> findAll(Sort sort);
Page<PaymentMethod> findAll(Pageable pageable);
List<PaymentMethod> findAll();
List<PaymentMethod> findAll(Sort sort);
List<PaymentMethod> save(Iterable<? extends PaymentMethods> entities);
void flush();
PaymentMethod saveAndFlush(PaymentMethods entity);
void deleteInBatch(Iterable<PaymentMethods> entities);

该接口是强类型(泛型)并自动为您实现的。对于每个实体,您所要做的就是创建一个扩展的接口。JpaRepository<T,Integer extends Serializable>

但是等等,还有更多!假设您有和持久字段。如果将以下方法添加到接口中:PaymentMethodnamevalidSince

interface PaymentMethodsDao extends JpaRepository<PaymentMethods, Integer> {

  Page<PaymentMethod> findByNameLikeAndValidSinceGreaterThan(
    String name, Date validSince, Pageable page
  );

}

框架将解析方法名称:

findBy (名称 like) (有效大于And

创建 JPA QL 查询,应用分页和排序 () 并为您运行它。无需实现:Pageable page

paymentMethodsDao.findByNameLikeAndValidSinceGreaterThan(
  "abc%",
  new Date(),
  new PageRequest(0, 20, Sort.Direction.DESC, "name"
);

结果查询:

SELECT *  //or COUNT, framework also returns the total number of records
FROM PaymentMethods
WHERE name LIKE "abc%"
  AND validSince > ...

并应用了分页。

唯一的缺点是该项目相当新,并且相对容易击中但是(但它非常积极地开发)。


推荐