# SpringDataJpa
# 简介
SpringDataJpa是SpringData的子项目,对jpa进行了封装。 好处:
- 与jpa和hibernate一样,可以跨数据库产品(只需要配置即可)
- Dao层只需要写接口,不需要写实现类
- 用法与jpa一致
# springboot整合与集成springdatajpa
一定要先继承jpa,然后才能集成springdatajpa。
# 继承体系结构
使用springdatajpa之后,dao层只有接口,没有 实现类了,无法添加@Repository注解,也就不能使用原先的扫描包方式了。
@Component @Controller @Service @Repository 这四个注解只能加在类上面,不能加在接口上面。 既然dao层只有接口没有实现类了,那么如何创建对象呢?
利用动态代理技术自动生成一个实现类,然后再创建对象。
springdatajpa扫描到这个包内的接口之后如何利用动态代理创建对象? springdatajpa底层会使用动态代理技术帮我们自动生成一个类叫$Proxy27,并且这个类实现了IUserDao接口。 并且生成的这个类叫$Proxy27这个类还继承了SimpleJpaRepository类。SimpleJpaRepository这个类实现了JpaRepository接口以及其父接口的所有方法。 所以这个子类$Proxy27就不需要再写任何东西了。因为子类已经继承了父类所有的方法。
IUserDao接口:
public interface IUserDao extends JpaRepository<Usee,Long> {
}
TIP
springdatajpa的dao层接口,只需要继承JpaRepository接口即可。 两个泛型: T: domain实体类的类型 ID: domain实体类中主键字段的类型
# 基本使用
findOne(id) // 查询一个,返回一个对象 findAll() // 查询所有,返回一个list集合 save(对象) //新增或者修改,insert / update,当主键有值的时候就修改,没有值的时候就新增 delete(id) 或者 delete(对象) // 删除
分页查询:
Pageable pageable = new PageRequest(2,5); // 从第3页查询,每页显示5个数据
Page<User> page = userDao.findAll(pageable);
System.out.println(page.getTotalElements()); // 总行数
System.out.println(page.getTotalPages()); //总页数
System.out.println(page.getSize()); //每页显示的行数
System.out.println(page.getNumberOfElements()); // 当前页有多少行数
System.out.println(page.getNumber()); // 当前页码
List<User> list = page.getContent(); // 当前页的数据集合
list.foreach(user -> System.out.println(user));
或者
page.foreach(user -> System.out.println(user));
/**
* Page接口是Iterable接口的子接口,所以Page对象直接迭代(也就是可以直接foreach)
**/
如果不做排序,默认按照主键id升序排序.
条件查询: 需要在自定义的接口中定义抽象方法才能使用. 抽象方法名称规则:
方法名称必须以findBy或者findAllBy开头
findBy或者findAllBy后面紧跟domain实体类中的属性名称(首字母转为大写)
遵守驼峰命名法
属性名称后面紧跟sql语句中的条件符号
- Like like
- Equals = In in
- Between between ... and ...
- LessThan <
- LessThanEqual <=
- GreaterThan >
- GreaterThanEqual >=
多个条件可以用And或者Or来连接,例如: findByNameLikeAndIdGreaterThanEqual() ==> select * from user where name like ? or id >= ?
方法参数的个数必须要与条件个数匹配,顺序要匹配,类型要匹配
缺陷: 这种通过方法名称的方式存在缺陷,因为实在太麻烦了.方法名称的规则太复杂繁琐.并且方法名会写的很长.
通过@Query注解来实现高级查询,jpql语句
@Query("select o from User o where o.name like ?1 or o.name like ?2")
List<User> findByNameLike(String name1,Sring name2);
原生sql语句
@Query(nativeQuery=true,value="select count(*) from user")
# 动态查询
Specification: 查询条件的接口,里面有一个实现类是我们必须自定义实现的。 自定义我们自己的Specification实现类。
Predicate toPredicate(Root<T> root,CriteriaQuery<?> query, CriteriaBuilder cb) ; //封装查询条件
root: 查询的根对象(查询的任何属性都可以从根对象中获取) CriteriaQuery: 顶层查询对象,自定义查询方式(了解,一般不用) CriteriaBuilder:查询的构造器,封装了很多的查询条件
示例:
自定义查询条件:
- 实现Specification接口(提供泛型,查询的对象类型)
- 实现toPredicate方法(构造查询条件)
- 需要借助方法参数中的两个参数( root: 获取需要查询的对象属性 CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配) ) 多条件拼接:
Specification<Customer> spec = new Specification<Customer>() {
@Override
public toPredicate(Root<Customer> root,CriteriaQuery<?> query, CriteriaBuilder cb){
return null;
}
};
Customer customer = customer.findOne(spec);
System.out.println(customer);
# 多表操作
# 表关系
一对一: 一对多:一的一方:主表,多的一方:从表。外键:需要再从表上新建一列作为外键,它的取值来源于主表的主键 多对多: 中间表:中间表中最少应该由两个字段组成,这两个字段作为外键指向两张表的主键,又组成了联合主键。
# 实体类中的关系
springdatajpa就是屏蔽了数据库,而采用面向对象的实体类来表示表关系。 包含关系,继承关系。
分析步骤:
- 明确表关系
- 确定表关系(描述 外键|中间表)
- 编写实体类,再实体类中描述表关系(包含关系)
- 配置映射关系
# 多表操作
多对多 →
关于评论
评论前请填好“昵称”、“邮箱”这两栏内容,否则不会收到回复,谢谢!