JPA简介及其使用详解
JPA简介及其使用详解
一、Spring data JPA简介
Spring data JPA是Spring在ORM(对象关系映射)框架,以及JPA规范的基础上,封装的一套JPA应用框架,并提供了一整套的数据访问层解决方案。
二.JPA常用注解
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表 |
@Table | 声明表名 |
@Basic | 指定非约束明确的各个字段 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性 |
@Id | 指定的类的属性,用于识别(一个表中的主键) |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中 |
@Column | 指定持久属性栏属性 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束 |
@ColumnResult | 参考使用select子句的SQL查询中的列名 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系 |
@ManyToOne | 定义了连接表之间的多对一的关系 |
@OneToMany | 定义了连接表之间存在一个一对多的关系 |
@OneToOne | 定义了连接表之间有一个一对一的关系 |
@NamedQueries | 指定命名查询的列表 |
@NamedQuery | 指定使用静态名称的查询 |
三、Spring data JPA的功能
Spring data JPA提供给用户使用的,主要有以下几个接口:
- Repository:仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
- CrudRepository:继承Repository,实现了一组CRUD相关的方法
- PagingAndSortingRepository:继承CrudRepository,实现了一组分页排序相关的方法
- JpaRepository:继承PagingAndSortingRepository,实现一组JPA规范相关的方法
- JpaSpecificationExecutor:比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法。
四、Spring data JPA接口
1、CrudRepository接口
该接口的定义如下,总共提供了11个方法,基本上可以满足简单的CRUD操作以及批量操作:
@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {<S extends T> S save(S entity);//保存<S extends T> Iterable<S> save(Iterable<S> entities);//批量保存T findOne(ID id);//根据id查询一个对象boolean exists(ID id);//判断对象是否存在Iterable<T> findAll();//查询所有的对象Iterable<T> findAll(Iterable<ID> ids);//根据id列表查询所有的对象long count();//计算对象的总个数void delete(ID id);//根据id删除void delete(T entity);//删除对象void delete(Iterable<? extends T> entities);//批量删除void deleteAll();//删除所有
}
2、PagingAndSortingRepository接口
PagingAndSortingRepository接口继承了CrudRepository接口。
只要继承了这个接口,Spring data JPA就已经为你提供了分页和排序的功能了。该接口的定义如下,主要提供了两个方法,供使用,其中T是要操作的实体类,ID是实体类主键的类型:
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {Iterable<T> findAll(Sort sort);// 不带分页的排序Page<T> findAll(Pageable pageable);// 带分页的排序
}
3、JpaRepository接口
如果业务需要即提供CRUD操作,又需要提供分页以及排序功能,那么就可以直接继承这个接口。该接口继承了PagingAndSortingRepository接口。
接口定义如下:
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {List<T> findAll();//查询所有对象,不排序List<T> findAll(Sort sort);//查询所有对象,并排序<S extends T> List<S> save(Iterable<S> entities);//批量保存void flush();//强制缓存与数据库同步T saveAndFlush(T entity);//保存并强制同步void deleteInBatch(Iterable<T> entities);//批量删除void deleteAllInBatch();//删除所有
}
4、JpaSpecificationExecutor接口
该接口提供了对JPA Criteria查询的支持。注意,这个接口很特殊,不属于Repository体系,而Spring data JPA不会自动扫描识别,所以会报找不到对应的Bean,我们只需要继承任意一个继承了Repository的子接口或直接继承Repository接口,Spring data JPA就会自动扫描识别,进行统一的管理。
编写接口如下:
public interface SpecificationExecutorRepository extends CrudRepository<User, Integer>,JpaSpecificationExecutor<User> {
}
Service类
@Service
public class SpecificationExecutorRepositoryManager {@Autowiredprivate SpecificationExecutorRepository dao;/*** 描述:根据name来查询用户*/public User findUserByName(final String name){return dao.findOne(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> query,CriteriaBuilder cb) {Predicate predicate = cb.equal(root.get("name"), name);return predicate;}});}/*** 描述:根据name和email来查询用户*/public User findUserByNameAndEmail(final String name, final String email){return dao.findOne(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {List<Predicate> list = new ArrayList<Predicate>();Predicate predicate1 = cb.equal(root.get("name"), name);Predicate predicate2 = cb.equal(root.get("email"), email);list.add(predicate1);list.add(predicate2);// 注意此处的处理Predicate[] p = new Predicate[list.size()];return cb.and(list.toArray(p));}});}/*** 描述:组合查询*/public User findUserByUser(final User userVo){return dao.findOne(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {Predicate predicate = cb.equal(root.get("name"), userVo.getName());cb.and(predicate, cb.equal(root.get("email"), userVo.getEmail()));cb.and(predicate, cb.equal(root.get("password"), userVo.getPassword()));return predicate;}});}/*** 描述:范围查询in方法,例如查询用户id在[2,10]中的用户*/public List<User> findUserByIds(final List<Integer> ids){return dao.findAll(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {return root.in(ids);}});}/*** 描述:范围查询gt方法,例如查询用户id大于9的所有用户*/public List<User> findUserByGtId(final int id){return dao.findAll(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {return cb.gt(root.get("id").as(Integer.class), id);}});}/*** 描述:范围查询lt方法,例如查询用户id小于10的用*/public List<User> findUserByLtId(final int id){return dao.findAll(new Specification<User>() {@Overridpublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {return cb.lt(root.get("id").as(Integer.class), id);}});}/*** 描述:范围查询between方法,例如查询id在3和10之间的用户*/public List<User> findUserBetweenId(final int start, final int end){return dao.findAll(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {return cb.between(root.get("id").as(Integer.class), start, end);}});}/*** 描述:排序和分页操作*/public Page<User> findUserAndOrder(final int id){Sort sort = new Sort(Direction.DESC, "id");return dao.findAll(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {return cb.gt(root.get("id").as(Integer.class), id);}}, new PageRequest(0, 5, sort));}/*** 描述:只有排序操作*/public List<User> findUserAndOrderSecondMethod(final int id){return dao.findAll(new Specification<User>() {@Overridepublic Predicate toPredicate(Root<User> root,CriteriaQuery<?> query, CriteriaBuilder cb) {cb.gt(root.get("id").as(Integer.class), id);query.orderBy(cb.desc(root.get("id").as(Integer.class)));return query.getRestriction();}});}
}
5、Repository接口
这个接口是最基础的接口,只是一个标志性的接口,没有定义任何的方法,那这个接口有什么用了?既然Spring data JPA提供了这个接口,自然是有它的用处,例如,我们有一部分方法是不想对外提供的,比如我们只想提供增加和修改方法,不提供删除方法,那么前面的几个接口都是做不到的,这个时候,我们就可以继承这个接口,然后将CrudRepository接口里面相应的方法拷贝到Repository接口就可以了。
总结:上述五个接口,开发者到底该如何选择?其实依据很简单,根据具体的业务需求,选择其中之一。因为各个接口之间并不存在功能强弱的问题。
五、Spring data JPA的查询
1、使用 @Query 创建查询
2、使用@NamedQueries创建查询
3、通过解析方法名创建查询
在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:
Keyword | Sample | JPQL snippet |
---|---|---|
And
|
findByLastnameAndFirstname
|
… where x.lastname = ?1 and x.firstname = ?2
|
Or
|
findByLastnameOrFirstname
|
… where x.lastname = ?1 or x.firstname = ?2
|
Is,Equals
|
findByFirstname ,findByFirstnameIs , findByFirstnameEquals
|
… where x.firstname = ?1
|
Between
|
findByStartDateBetween
|
… where x.startDate between ?1 and ?2
|
LessThan
|
findByAgeLessThan
|
… where x.age < ?1
|
LessThanEqual
|
findByAgeLessThanEqual
|
… where x.age ⇐ ?1
|
GreaterThan
|
findByAgeGreaterThan
|
… where x.age > ?1
|
GreaterThanEqual
|
findByAgeGreaterThanEqual
|
… where x.age >= ?1
|
After
|
findByStartDateAfter
|
… where x.startDate > ?1
|
Before
|
findByStartDateBefore
|
… where x.startDate < ?1
|
IsNull
|
findByAgeIsNull
|
… where x.age is null
|
IsNotNull,NotNull
|
findByAge(Is)NotNull
|
… where x.age not null
|
Like
|
findByFirstnameLike
|
… where x.firstname like ?1
|
NotLike
|
findByFirstnameNotLike
|
… where x.firstname not like ?1
|
StartingWith
|
findByFirstnameStartingWith
|
… where x.firstname like ?1 (parameter bound with appended % )
|
EndingWith
|
findByFirstnameEndingWith
|
… where x.firstname like ?1 (parameter bound with prepended % )
|
Containing
|
findByFirstnameContaining
|
… where x.firstname like ?1 (parameter bound wrapped in% )
|
OrderBy
|
findByAgeOrderByLastnameDesc
|
… where x.age = ?1 order by x.lastname desc
|
Not
|
findByLastnameNot
|
… where x.lastname <> ?1
|
In
|
findByAgeIn(Collection<Age> ages)
|
… where x.age in ?1
|
NotIn
|
findByAgeNotIn(Collection<Age> age)
|
… where x.age not in ?1
|
True
|
findByActiveTrue()
|
… where x.active = true
|
False
|
findByActiveFalse()
|
… where x.active = false
|
IgnoreCase
|
findByFirstnameIgnoreCase
|
… where UPPER(x.firstame) = UPPER(?1)
|
JPA简介及其使用详解相关推荐
- Nginx 反向代理工作原理简介与配置详解
Nginx 反向代理工作原理简介与配置详解 测试环境 CentOS 6.8-x86_64 nginx-1.10.0 下载地址:http://nginx.org/en/download.html 安装 ...
- Android OkHttp3简介和使用详解
一 OKHttp简介 OKHttp是一个处理网络请求的开源项目,Android 当前最火热网络框架,由移动支付Square公司贡献,用于替代HttpUrlConnection和Apache HttpC ...
- FTP服务的简介和配置详解
FTP服务的简介和配置详解 注意:配置FTP服务时,最好关闭防火墙和selinux 1.FTP服务简介 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为& ...
- Spring Data JPA 之 @Query 语法详解及其应用
5 Spring Data JPA 之 @Query 语法详解及其应用 5.1 快速体验 @Query 的方法 沿⽤我们之前的例⼦,新增⼀个 @Query 的⽅法: // 通过 query 注解根据 ...
- DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析)、使用方法(NLP领域/CV领域)、案例应用之详细攻略
DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析).使用方法(NLP领域/CV领域).案例应用之详细攻略 目录 Transfo ...
- HAProxy 简介及配置文件详解
文章目录 1.HAProxy简介 2.HAProxy特点和优点: 3.HAProxy保持会话的三种解决方法 4.HAProxy的balance 8种负载均衡算法: 5.HAProxy 主要工作模式 6 ...
- Spark之 spark简介、生态圈详解
来源:http://www.cnblogs.com/shishanyuan/p/4700615.html 1.简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorith ...
- java jpa注解哪个包好,Spring Data JPA 中常用注解详解
一.java对象与数据库字段转化 @Entity:标识实体类是JPA实体,告诉JPA在程序运行时生成实体类对应表 @Table:设置实体类在数据库所对应的表名 @Id:标识类里所在变量为主键 @Gen ...
- 一张图解释什么是遗传算法_遗传算法简介及代码详解
(allele) 数据值,属性,值 基因座 (locus) 位置, iterator 位置 表现型 (phenotype) 参数集,解码结构,候选解 染色体:又可以叫做基因型个体 (individua ...
- git 添加用户名和邮箱_Git实用教程(二) | Git简介及安装详解
Git实用教程专栏回顾 Git实用教程(一) | 为什么需要版本控制?(以嵌入式项目开发为例) 1.Git简介 Git(官网 https://git-scm.com/)是一个免费开源的分布式版本控制系 ...
最新文章
- c和python区别_C语言和python的区别
- tensorflow-eagerAPI
- Angular CLI 全局 ng.cmd 文件内容分析
- 通过快速Java和文件序列化加快速度
- C++ 的门门道道 | 技术头条
- Pidgin 新QQ插件:pidgin-lwqq
- Vue Element校验validate
- 大K提醒各位常备DOS杀毒盘
- 关于只针对ie7浏览器的css问题
- 【扩频通信】基于matlab GUI扩频通信系统仿真【含Matlab源码 772期】
- 使用SecureCRT工具上传、下载文件的两种方法
- 小猫跳圈-第12届蓝桥杯Scratch省赛3真题第1题
- 汽修汽配进销存 好用的汽修汽配行业管理软件 汽修汽配老板最常用的进销存软件
- 下载网站的ICO图标方法
- 领导力21法则自测题
- 一键模拟登陆华师大公共数据库!ver2.0
- 如何批量将png格式改成jpg?
- 跨国公司“中国设计”
- 数字传输系统的最佳接收与误码分析-python实现
- ASP.NET 对路径的访问被拒绝
热门文章
- excel对比两顺序不同的表格
- 软件设计师考试都考什么内容
- 软件设计师中级考试,软考
- 光谱共焦位移传感器原理和特性
- 开氏温度与摄氏度换算_政策丨车厢温度变化2……冷藏保温车国标开始征求意见...
- Java技术栈思维导图
- GameFramework框架——UI底层框架梳理
- 单词毕业设计,微信小程序毕设,小程序毕设源码,单词天天斗 (毕业设计/实战小程序学习/微信小程序完整项目)
- 细说 MySQL登录
- R语言绘制韦布尔分布图和泊松(Poisson)分布图,并为二项分布(泊松分布)绘制不同颜色