SpringData JPA
SpringData JPA
JPA是规范:本质上是一种ORM规范,不是框架。
SpringData JPA是封装基于jpa规范的一套应用框架。
- findOne(long id)
- sava(eneity)
- findAll(long id)
- delete(long id)
实现原理:
通过动态代理的方式,自动生成代理对象。
- 通过JdkDynamicAopProxy的invoke方法创建动态代理实现
- SimpleJpaRepository当中封装了JPA的操作(基本crud)
- 通过hibernate完成数据库操作。
复杂查询:
-
借助接口中定义好的查询方法。
- count() 统计总条数
- boolean exists(long id)
- findOne 立即加载 与 方法,延迟加载。
-
使用jpql查询。在实体类的属性上添加@Query
@Query(value=“from user where name=?”)
public User getUser(String name) ;- 有多个占位数参数,默认情况下,占位符的位置需要和方法中的参数位置保持一致
- 也可以指定参数的位置 ?索引的方式 指定取参数中第几个值。
- @Modifying 声明这是个更新参数。
- 进行更新或删除操作时,需要添加事务和设置不回滚操作。
-
SQL查询
- @Query 中value:jpql语句 | sql语句
- nativeQuery=true 代表sql查询。 false jpql查询
-
方法名称规则查询,是对jpql查询更加深入的封装。
- findBy查询(对象的属性名首字母大写) 例如 findByCustName
- 模糊查询 findBy+实体类属性名+查询方式 (like|isnull) findByCustNameLike
- 多条件查询 findBy+实体类属性名+查询方式 (like|isnull)+连接符(and|or)+属性名+查询方式 (like|isnull) findByCustNameLikeAndCustIdustry()
自定义查询条件:
- 实现specification接口(提供泛型)
- 实现toPredicate方法(构造查询条件)
- 借助方法中的两个参数
- root 获取 查询对象的属性
- CriteriaBuilder:构造查询条件的,内部封装了很多查询条件(模糊匹配,精准匹配)
分页:
使用Pageable接口,pageRequest实现类 ,使用构造方法创建
第一个参数,查询当前页的页数,第二个参数,煤业查询的数量。
page.getContent();//得到内容数据集合列表
page.getTotalElements();//得到总条数
page.getTotalPages();//得到总页数
多表查询
表关系:
- 一对一
- 一对多
- 一的一方:主表
- 多的一方:从表
- 外键:需要在从表上建立一列作为外键,值为主表的主键
- 多对多
- 中间表:至少两个字段组成,这两个字段作为外键指向两张表的主键,又组成联合主键。
1、一对多
老师对学生:一对多
实体类的关系:
包含关系:通过实体类的包含关系来描述表关系
继承关系
分析步骤:
- 明确表关系
- 确定表关系(描述 外键|中间表)
- 编写实体类。用实体类描述表关系(包含关系)
- 配置映射关系
客户和联系人之前的关系:一对多
- 客户实体类:相对于本身,一对多,使用集合保存联系人,推荐使用Set
使用@OneToMany(targetEntity = linkMan.class)
targetEntity :对方的字节码对象
@JoinColumn配置外键
name:外键字段名称 referenceColumnName参照主表的主键字段名称
需要在1的一方,添加了外键的配置,所以对客户而言,也具备了维护外键的作用。
@OneToMany(targetEntity = linkMan.class)
@JoinColumn(name="从表表示外键的字段",referenceColumnName="主表的主键")
private Set linkMans
-
联系人实体类:相对于本身,多对一,实体类中包含了客户的对象。
@ManyToOne(targetEntity = Customer.class)
@JoinColumn(name="从表 表示外键的字段",referenceColumnName="主表的主键")
private Customer customer
当两边都配置外键关系时,是双向外键维护。
一的一方,会多执行一条update语句维护外键。
多的一方,会直接在insert中维护外键。
双向绑定会多执行一条update语句,如果不需要执行,那么一的一端需要主动放弃外键维护权。
mappedBy:对方配置关系的属性名称
@OneToMany(mappedBy = "customer")
private Set linkMans
一对多的删除
删除主表数据时
- 当从表有数据
- 在默认情况,会把外键字段置为null,然后删除主表数据,如果从表外键字段有非空约束,默认情况就会报错。
- 如果配置了放弃维护关联关系的权力,则不能删除,因为在删除时,根本不会去更行从表的字段
- 如果还想删除,使用级联删除引用。
级联
操作对象的同时,同时操作他的关联对象。
级联操作:
- 需要区分操作主体
- 需要在操作的主体的实体上,添加级联属性
- cascade(配置级联)
级联添加
保存一个客户的同时,保存客户的所有联系人
需要在操作主体的实体上,配置casacde属性
ALL:所有
MERGE :更新
PERSIST:保存
REMOVE:删除
@OneToMany(mappedBy = "customer" cascade=CascadeType.ALL)
private Set linkMans
级联删除
删除1号客户的同时,删除1号客户的所有联系人。
2、多对多
案例:用户和角色
用户:用户有很多角色
角色:角色可分配给多个用户
配置多对多的映射关系
-
申明表关系的配置
- @ManyToMany(targetEntity = Role.class) //多对多
-
配置中间表
//User.java
@ManyToMany(targetEntity = Role.class)
@JoinTable(name = "sys_user_role",
//joinColumns,当前对象在中间表的外键
joinColumns = {@joinColumn(name = "sys_user_id", referenceColumnName = "user_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@joinColumn(name = "sys_role_id", referenceColumnName = "role_id")})
private Setroles = new HashSet<>(); //Role.java
@ManyToMany(targetEntity = User.class)
@JoinTable(name = "sys_user_role",
//joinColumns,当前对象在中间表的外键
joinColumns = {@joinColumn(name = "sys_role_id", referenceColumnName = "role_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@joinColumn(name = "sys_user_id", referenceColumnName = "user_id")})
private Setusers = new HashSet<>();
多对多放弃维护权,被动一方放弃维护权。
//User.java
@ManyToMany(targetEntity = Role.class)
@JoinTable(name = "sys_user_role",
//joinColumns,当前对象在中间表的外键
joinColumns = {@joinColumn(name = "sys_user_id", referenceColumnName = "user_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@joinColumn(name = "sys_role_id", referenceColumnName = "role_id")})
private Set roles = new HashSet<>();
//Role.java
@ManyToMany(mappedBy = "roles")
private Set users = new HashSet<>();
级联
多对多支持级联
多表的查询
-
对象导航查询
查询一个对象的同时,通过此对象查询他的关联对象。
默认使用延迟加载的方式查询,调用get方法不会立即发送查询,而是在使用关联对象的时候才会出现查询。
不使用延迟加载,需要配置。
fetch ,需要配置到多表映射关系的注解上。EAGER 立即加载 LAZY延迟加载@ManyToMany(mappedBy = "roles" , fetch = FetchType.EAGER)
EAGER 立即加载 底层实现,通过连表(left join)的方式实现,不推荐立即查询
一对多中 从多的一方查询,默认使用立即加载。将其中1的一方一起查询出来。
从一表查询多方
*默认:使用延迟加载。
多方查询一方
*默认使用:立即加载。