Java中的数据库访问经历了一些步骤:
- 首先,纯JDBC
- 专有框架
- EJB实体和JDO等标准
- 开源框架,例如Hibernate和EclipseLink (当时称为TopLink)
当JPA最终发布时,我的愿望似乎实现了。 最后,有一个标准来自Java来访问数据库
不幸的是,与Hibernate相比,JPA没有兑现承诺:例如,您没有Query by Example 。 更糟糕的是,在第一个版本中,JPA没有提供诸如Criteria之类的简单功能,因此即使简单的查询也必须通过JPQL实现,并因此通过String级联来实现。 恕我直言,这完全打败了ORM的目的。
JPA2抢救
最后,JPA2提供了在实际应用程序中可用的功能。 但是,我觉得仍然有很多样板代码可以编写一个简单的CRUD DAO :
publicclassJpaDao{
@PersistenceContext
privateEntityManagerem;
privateClassmanagedClass;
privateJpaDao(ClassmanagedClass){
this.managedClass=managedClass;
}
publicvoidpersist(Eentity){
em.persist(entity);
}
publicvoidremove(Eentity){
em.remove(entity);
}
publicEfindById(PKid){
returnem.find(managedClass,id);
}
}
有些人会(并且确实)反对在这种用例中不需要DAO:只需将EntityManager
注入服务类中并直接使用即可。 这可能是一个相关的观点,但是只有在没有查询的情况下,才需要在数据访问和业务逻辑之间进行区分。
JPA2中的样板代码
两个简单的用例突出了JPA 2: @NamedQuery
和简单条件查询中无用的样板代码。 在第一种情况下,您必须通过实体管理器获取命名查询的句柄,然后像下面这样设置潜在参数:
Queryquery=em.createNamedQuery("Employee.findHighestPaidEmployee");
在第二个中,您必须使用CriteriaBuilder
实现自己的查询:
CriteriaBuilderbuilder=em.getCriteriaBuilder();
CriteriaQueryquery=builder.createQuery(Person.class);
RootfromPerson=query.from(Person.class);
returnem.createQuery(query.select(fromPerson)).getResultList();
恕我直言,这些代码行什么都没有带到桌上,只是使我们自己的代码混乱。 一次偶然的机会,我发现了Hades项目,该产品基于此结论并为您编写了简单的代码。
Spring Data JPA
鉴于一些出色的OpenSource项目的命运,Hades的表现要好得多,因为Hades已经以Spring Data JPA的名称引入了Spring生态系统。 SDJ开箱即用,提供具有高级CRUD功能的DAO。 例如,以下接口可以按原样使用:
publicinterfaceEmployeeRepositoryextendsJPARepository
给定一些Spring魔术,将在运行时提供以下方法的实现:
-
void deleteAllInBatch()
-
void deleteInBatch(Iterable<Employee> entities)
-
List<Employee> findAll()
-
List<Employee> findAll(Sort sort)
-
void flush()
-
<S extends Employee> List<S> save(Iterable<S> entities)
-
Employee saveAndFlush(Employee entity)
-
Page<Employee> findAll(Pageable pageable)
-
Iterable<Employee> findAll(Sort sort)
-
long count()
-
void delete(ID id)
-
void delete(Iterable<? extends Employee> entities)
-
void delete(Employee entity)
-
void deleteAll()
-
boolean exists(Long id)
-
Iterable<Employee> findAll()
-
Iterable<Employee> findAll(Iterable ids)
-
Employee findOne(Long id)
-
<S extends Employee> Iterable<S> save(Iterable<S> entities)
-
<S extends Employee> S save(S entity)
是的,SDJ为您提供了一个通用的DAO,就像周围的许多框架一样,但是在这里,与底层实现的连接由该框架免费处理。 对于那些不需要全部并且更喜欢严格的最低要求的人,您还可以使用以下策略,在其中您必须从上面的列表中选择方法(并使用注释):
@RepositoryDefinition(domainClass=Employee.class,idClass=Long.class)
publicinterfaceEmployeeRepository{
longcount();
Employeesave(Employeeemployee);
}
确实不错,但是最好的还没到。 还记得我们不得不自己编写的上述两个用例吗? 第一种方法很简单,只需将不合格的查询名称添加到接口即可,如下所示:
@RepositoryDefinition(domainClass=Employee.class,idClass=Long.class)
publicinterfaceEmployeeRepository{
...
EmployeefindHighestPaidEmployee();
}
JPA存储库中提供了第二个用例,查找所有员工。 但是,让我们假装一秒钟,我们有一个WHERE
子句,例如名字。 SDJ能够根据方法名称处理简单查询:
@RepositoryDefinition(domainClass=Employee.class,idClass=Long.class)
publicinterfaceEmployeeRepository{
...
ListfindByLastname(StringfirstName);
}
我们只需要编写一个接口及其方法的代码:不涉及实现代码或元模型的生成! 不用担心,如果您需要实现一些复杂的查询,则SDJ允许您连接自己的实现。
结论
如果您已经是Spring用户,那么Spring Data JPA确实是(真的!)必须。 如果不是,那么欢迎您对其进行测试,以亲自查看其附加值。 恕我直言,SDJ是JavaEE尚未杀死Spring的原因之一:它桥接了注入部分,但样板代码仍然无处不在。
本文不是一个方法,而是一个让您进入SDJ的预告片。 您可以在此处以Maven / Eclipse格式找到本文的资源。
对于尚未加入JPA的用户,可以使用Data JDBC ; 对于那些远远超出此范围的用户(认为大数据); 有一个数据Hadoop 。 检查所有Spring Data项目 !
翻译自: https://blog.frankel.ch/easier-jpa-with-spring-data-jpa/