spring jpa 主要分为三个类:
org.springframework.data.jpa.repository.JpaRepository<T, ID>
org.springframework.data.jpa.repository.JpaSpecificationExecutor<T>
org.springframework.data.repository.CrudRepository<T, ID>
这三个类的实现类都是
org.springframework.data.jpa.repository.support.SimpleJpaRepository<T, ID>(这个类挺牛逼的)
其中
JpaRepository主要是findall findpage findone这样的方法
JpaSpecificationExecutor主要是findall(spec) findpage(spec) findone(spec)这样的方法
spec-->查询条件,需要接口org.springframework.data.jpa.domain.Specification<T>这个接口
并且实现
org.springframework.data.jpa.domain.Specification.toPredicate(Root<T>, CriteriaQuery<?>, CriteriaBuilder)
这个接口中有三个参数:
Root
CriteriaQuery
CriteriaBuilder
其中 Root是查询结果的一个实体对象,也就是查询结果返回的主要对象,其中一对多OR多对一就是从这个对象开始计算的,具体层级关系
javax.persistence.TupleElement<X>
javax.persistence.criteria.Selection<X>
javax.persistence.criteria.Expression<T>
javax.persistence.criteria.Path<X>
javax.persistence.criteria.From<Z, X>
javax.persistence.criteria.Root<X>
这几个接口主要用于描述一个数据库对象与实体对象的对应关系,就不多说了。
然后是javax.persistence.criteria.CriteriaQuery<T>,这个是JPA标准,主要是构建查询条件的,里面的方法都是各种查询方式:distinct、select、where、groupby、having、orderby这些方法,想必大家都知道这些是组件SQL语句的基本方法。
接下来是javax.persistence.criteria.CriteriaBuilder,这个接口主要是用来进行一些函数操作,不过我们这里先关注JPA标准中Hibernate的两个实现方法:
1.and org.hibernate.ejb.criteria.CriteriaBuilderImpl.and(Predicate...)
2.or org.hibernate.ejb.criteria.CriteriaBuilderImpl.or(Predicate...)
这两个方法都有一个关键的接口:Predicate(javax.persistence.criteria.Predicate);
这个接口,同为Expression(javax.persistence.criteria.Expression<Boolean>)的子接口,可以肯定也是字段相关的表达式,在实际操作中,这个接口也是作为关联各种Predicate的核心操作接口,and方法是将各个条件作为and来拼接,进行查询;or是将各条件作为or来拼接,进行查询。
然后说如何生成一个Predicate接口,生成的核心类还是上面的CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder),在这个接口中,很多方法都是返回Predicate接口的,其中包含between、gt(大于)、lt(小于)、not(非)等等操作,将所需要的这些查询条件都放在一个array数组(或者采用java.util.ArrayList.toArray(T[])-->cb.and(predicateList.toArray(new Predicate[predicates.size()]))),然后调用上一步说的and或者or方法进行拼接,当然,如果一个查询既有and又有or,用这种方式还没有具体尝试过,有待考证。
说了这么多,先总结一下
Specification的toPredicate这个方法声明了
Root:查询哪个表
CriteriaQuery:查询哪些字段,排序是什么
CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
Predicate(Expression):单独每一条查询条件的详细描述
这些,就是有条件查询的使用方式,springJPA和hibernate的完美结合(如果只用springJPA,根本了解不到这里)
来个简单的例子吧:
/** 查询名字包含icarus,或者手机号包含188的用户(如果return中的or改为and,就是查询名字包含icarus,并且手机号包含188的用户) */
// query = cb.createQuery(User.class);// query是这么出来的
List<Predicate> predicateList = new ArrayList<>();
root = query.from(User.class);
Path<String> nameExp = root.get("name");
Predicate p1 = cb.like(nameExp, "%icarus%");
Path<String> phoneExp = root.get("phone");
Predicate p2 = cb.like(phoneExp, "%188%");
predicateList.add(p1);
predicateList.add(p2);
return cb.or(predicateList.toArray(new Predicate[predicates.size()]));
如果想提炼抽象类,则需要将返回predicateList这个方法给抽象化,不过这时候就无法提供OR和AND双重选择了。
当然,通过其它参数判断也可以,不过优势也不大。
如果想通过判断,推荐Predicate这个类里面的枚举值AND和OR
在CriteriaBuilder中,还有asc、desc两个方法,返回Order(此处order在CriteriaQuery中使用,和下面PageRequest说的order、sort不同);还有sum、count、avg、max、min这几个方法,聚合函数理论上是返回值中才会出现的,这里出现,暂且还真不知道什么用处,不过肯定有用,还望高人指点一下。
以上,是关于springJPA在进行条件查询时使用的方式。不能说简单了,因为方法并没有直接写SQL的优势,好的是跨平台,相信hibernate的夸数据库执行是很给力的
P.S. 这种设计模式在以前做一个日本的项目时遇见过,每一个查询条件都采用一个方法累加的手段,好的一方面是方法式增加查询条件、不用管实现方式、可使用于不同的数据库,针对专注java开发的程序员比较友好一些;坏处也很明显,繁琐、效率低,这些毋庸置疑,毕竟从HQL到SQL还需要很长的转换。
还没完,继续
刚才只是说了条件查询中的Specification,包含的内容相当多,然后再说下查询结果相关的内容。
findall和findall(spec)这两个方法比较简单,返回对象是List<T>
其中T在findall中指定的是JpaRepository中的第一个泛型对象,
在findall(spec)中指定的是JpaSpecificationExecutor中的第一个泛型对象,
也就是与数据库对应的实体类一样(spec还应该和root对应,因为Specification也需要泛型,应该在写Specification的时候就指定了)
findone和findone(spec)返回对象是T,T也同findall
额外在说一下findall(sort)和findall(pageable),其返回结果是org.springframework.data.domain.Page<T>
P.S.(因为findall(spec,sort)和findall(spec,pageable)和这两个区别不是很大,就不在额外赘述了,自行理解吧)
在这里又出来两个参数:sort和pageable
sort:实质就是一组order(此order不是上面CriteriaBuilder中通过asc和desc生成的order接口,而是sort的一个内部公开类(理解成一个普通类就行),是一个实现类),sort的生成可以使用一个order数组、order列表、属性数组、属性列表。采用order的好处是可以自定义排序方向(order由属性和方向组成),若采用属性,则默认使用ASC升序排列
说完了sort,我们再来说说pageable
pageable指的是org.springframework.data.domain.Pageable,这个接口有4个方法,
getPageNumber-->获取页码
getPageSize -->分页大小
getOffset -->偏移量
getSort -->获取排序信息
对于pageable的产生,也很容易,采用org.springframework.data.domain.PageRequest这个实现类,将构造方法生成出来即可,没有第二个实现类。将sort、pageNumber、getPageSize设置好即可
偏移量不允许设置,这个是在查询的时候,通过计算页码和分页大小进行自动设置的
对于方法返回值:Page,实现类org.springframework.data.domain.PageImpl<T>也很简单,仅仅是在List的基础上增加了总页码、总大小等一系列常用内容,看代码即可
以下,是spring官方对jpa的文档,英文能力不错的可以阅读原文。
http://docs.spring.io/spring-data/jpa/docs/1.8.0.RELEASE/reference/html/
不过原文大多讲的是应用方向的
- 浏览: 196629 次
- 来自: ...
最新评论
-
Norther:
注入都比较麻烦 现在的折衷办法就是回归原始 在DomainOb ...
使用Spring的情况下如何将Dao注入DomainObject? -
pig345:
最近也在看这个问题,spring确实 和 DomainObje ...
使用Spring的情况下如何将Dao注入DomainObject? -
piper:
版主,需要这么复杂的配置吗?我记得以前和ehcache结合的时 ...
using springmodules-cache -
littcai:
支持一下,正准备实践一下
using springmodules-cache -
huangxx:
没有实践过
支持分享
using springmodules-cache
相关推荐
Spring Data JPA 允许你在基础接口上添加额外的方法,并提供具体的实现。 8. ** Transactions**:Spring Data JPA 使用 Spring 的事务管理支持,可以方便地配置事务边界,确保数据操作的一致性。 9. **JPA ...
Spring Data JPA 是一个强大的框架,它简化了Java应用程序与数据库之间的交互,是Spring生态中的重要组成部分。通过使用Spring Data JPA,开发者可以避免编写大量的JPA(Java Persistence API)和SQL代码,专注于...
Spring Data JPA API。 Spring Data JPA 开发文档。 官网 Spring Data JPA API。
只需要在接口上定义方法名,Spring Data JPA就能自动生成对应的SQL语句。例如,`findAll()`会执行SELECT ALL查询,`findByUsername(String username)`将生成一个根据用户名查找的查询。此外,`Pageable`接口可用于...
3. **Spring Data JPA概述**:Spring Data JPA是Spring对JPA的扩展,它提供了自动化的数据访问层,包括查询方法的自动实现、Repository接口的定义以及定制化查询等功能。 4. **Repository接口**:Spring Data JPA的...
然而,尽管Spring Data JPA带来了诸多便利,但在实际使用中也会遇到一些挑战和难点: 1. **SQL性能问题**: - Spring Data JPA虽然简化了查询编写,但可能导致生成的SQL不够优化,尤其是在处理大数据量或复杂查询...
在使用 Spring Data JPA 时,可能会遇到一些特定的异常,如 `EntityNotFoundException`(未找到实体)、`OptimisticLockingFailureException`(乐观锁失败)等,需要正确捕获并处理。 在黑马程序员的 JavaEE 57期...
JpaRepository 是 Spring Data JPA 中提供的一个基础接口,它扩展自 PagingAndSortingRepository,并且增加了一些额外的、常用的操作方法。通过实现 JpaRepository 接口,开发者可以得到一系列的预定义方法,例如...
如果默认的CRUD方法不能满足需求,可以通过在Repository 接口中定义查询方法,Spring Data JPA 会根据方法名自动构建SQL。例如,`findByEmail` 方法会生成一个查找指定邮箱用户的查询。 6. **Service 层** 在业务...
通过Spring Data JPA,我们可以直接通过接口定义来实现对数据库的CRUD操作,无需编写大量的DAO层代码。只需提供一个继承自JpaRepository的接口,即可自动实现基本的查询方法。此外,Spring Data JPA还支持自定义查询...
Spring Data JPA是Java开发中的一个关键框架,它简化了与关系型数据库的交互,特别是基于Java Persistence API (JPA)。这个框架是Spring生态系统的组成部分,为开发者提供了声明式数据访问的方式,允许通过简单的...
在接口中定义的方法名,SpringDataJPA会根据命名规则自动识别该方法需要完成什么操作,并且自动生成相应的实现代码。开发者可以使用如下几种方式来定义接口: 1. 继承`JpaRepository`接口,该接口提供了大量通用的...
例如,如果我们要查询用户表的部分字段,只需定义一个返回值为UserDto的接口方法,Spring Data JPA会自动解析并执行对应的SQL。 2. **联合查询映射自定义对象**:Spring Data JPA支持JOIN查询,并能将结果映射到...
2. **Query 方法**:在Repository接口中,可以定义方法名,Spring Data JPA会根据方法名自动构造对应的JPA查询。例如,`findAll()`对应于SQL的`SELECT * FROM table`,`findByUsername(String username)`对应于`...
Spring Data JPA是Spring生态系统中的一个重要组件,它为开发者提供了与JPA(Java Persistence API)交互的简化接口,极大地提高了数据访问的效率。本教程将深入探讨如何在Spring Boot项目中整合Spring Data JPA,...
1. **简化的查询**:使用Spring Data JPA,只需要定义接口方法名,就可以生成相应的SQL查询,减少了对SQL的直接依赖。 2. **类型安全的查询**:由于查询是基于方法签名生成的,因此可以避免因拼写错误导致的运行时...
总结来说,Spring Data JPA大大简化了与数据库的交互,通过方法命名查询和`@Query`注解,我们可以轻松地完成各种复杂的查询操作,包括排序和分页。在实际开发中,这将提高我们的工作效率,降低出错的可能性。通过...
Spring Data JPA 提供了自动化的 CRUD 操作接口。创建一个继承自 `JpaRepository` 的接口,例如 `UserRepository.java`: ```java import org.springframework.data.jpa.repository.JpaRepository; public ...