如何创建提供 crud 操作的通用 DAO,而无需通过不提供其他方法的自定义 DAO 对其进行扩展

Posted

技术标签:

【中文标题】如何创建提供 crud 操作的通用 DAO,而无需通过不提供其他方法的自定义 DAO 对其进行扩展【英文标题】:How to create generic DAO that delivers crud operation without the need to extend it by custom DAO that doesn't deliver others methods 【发布时间】:2016-12-19 11:17:29 【问题描述】:

我有通用 DAO:

@NoRepositoryBean
interface ICrudDao<T, ID extends Serializable> extends Repository<T, ID> 
    void delete(T deleted);

    List<T> findAll();

    T findOne(ID id);

    T save(T persisted);

为了让服务能够工作,我必须创建允许自定义实体获得持久性的接口,例如:

interface TodoDao extends ICrudDao<Todo, Long> 


我有很多像 TodoDao 这样的 daos。然后不要传递任何特殊的方法。

创建大量空接口似乎是个愚蠢的想法。如何创建一个通用的?

【问题讨论】:

请接受给定的答案之一或说明为什么这些解决方案不符合您的问题描述。 最接近的解决方案是:SEY_91。但我需要实体上的具体类型,而不是所有的 Todo。 为 Spring Data / JPA 添加了说明 【参考方案1】:

编辑: 我不认为你试图做的是一个好主意。起初为每个实体注册一个存储库似乎是样板代码,但随着应用程序的增长,它将帮助您维护它。想象一下您的应用程序随着时间的推移会像这样发展:

    您创建了一个简单的实体 Person 和接口 PersonRepository。幸运的是,所有基本的 CRUD 操作都已包含在内,到目前为止它符合您的需求,因此无需执行其他操作。 随着应用程序的增长,Person 会获得很多关联关系,例如 Address、Job、Hobbies,并且每次访问它时获取所有关联数据的效率非常低,因为并非总是需要每个关联。要遇到这种情况,您在 PersonRepository 中创建自己的方法,该方法执行您自己的 NamedQuery 以仅加载某些字段并将其存储在特定视图所需的 DTO 中(“SELECT new package.PersonDto(x,y) FROM PERSON WHERE ... )。

    随着时间的推移,您会发​​现自己需要以动态方式执行查询,例如分页或只需要在特定条件下添加的限制。因此,您创建了一个新接口 PersonCustomRepository 和 PersonCustomRepositoryImpl,您可以在其中以编程方式编写查询:

    @PersistenceContext
    private EntityManager entityManager;
    
    @Transactional
    public List<Person> foo() 
       // example for accessing hibernate directly, you could also use QueryDSL and so on
       Criteria basicCriteria = entityManager.unwrap().createCriteria(Person.class);
       if (someCondition) 
          criteria.add(Restrictions.eq("foo", foo));
          ...
       
       ...
       return criteria.list();
    
    

底线: Spring 数据存储库已经为您做了很多工作,并且它们很容易扩展,不要试图与您的框架抗衡,即使它可能会在一开始就为您节省一些点击次数地点。

【讨论】:

你可以分享一个代码。声明和使用这些存储库? 但仍然要获得我必须创建自定义类的实体。我想要一个通用的来处理我的所有实体。【参考方案2】:

您可以通过使您的实体通用来避免这种情况。

//you can annotated with @MappedSuperclass
public class BaseBean
 //you can specify the id here


public class Todo extends BaseBean 



@NoRepositoryBean
interface ICrudDao<T exntends BaseBean, ID extends Serializable> extends Repository<T, ID> 
    void delete(T deleted);

    List<T> findAll();

    T findOne(ID id);

    T save(T persisted);

【讨论】:

但是我从 db 获得的所有实体都将是只有 id 的 BaseBean,我不想使用特定类型,例如:Todo【参考方案3】:

我认为这是不可能的。请参阅 How to create a Generic DAO class using Hibernate Context sessions 和 Hibernate: CRUD Generic DAO 这些可能会有所帮助。 我还可以将Hibernate Session 视为处理所有类型对象的持久性的单个类的示例,它只处理对象类型。

【讨论】:

以上是关于如何创建提供 crud 操作的通用 DAO,而无需通过不提供其他方法的自定义 DAO 对其进行扩展的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用 java 和 jdbc(无 ORM)为基本的 crud 操作实现通用 DAO?

为 Hibernate 创建一个通用的 DAO 类

Generic Hibernate DAO

Java CRUD DAO持久性设计

java oop第09章_JDBC02(CRUD操作)

如何使用 JDBC 创建事务性 DAO