# 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升序排序.

条件查询: 需要在自定义的接口中定义抽象方法才能使用. 抽象方法名称规则:

  1. 方法名称必须以findBy或者findAllBy开头

  2. findBy或者findAllBy后面紧跟domain实体类中的属性名称(首字母转为大写)

  3. 遵守驼峰命名法

  4. 属性名称后面紧跟sql语句中的条件符号

    • Like like
    • Equals = In in
    • Between between ... and ...
    • LessThan <
    • LessThanEqual <=
    • GreaterThan >
    • GreaterThanEqual >=
  5. 多个条件可以用And或者Or来连接,例如: findByNameLikeAndIdGreaterThanEqual() ==> select * from user where name like ? or id >= ?

  6. 方法参数的个数必须要与条件个数匹配,顺序要匹配,类型要匹配

缺陷: 这种通过方法名称的方式存在缺陷,因为实在太麻烦了.方法名称的规则太复杂繁琐.并且方法名会写的很长.

通过@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:查询的构造器,封装了很多的查询条件

示例:

自定义查询条件:

  1. 实现Specification接口(提供泛型,查询的对象类型)
  2. 实现toPredicate方法(构造查询条件)
  3. 需要借助方法参数中的两个参数( 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就是屏蔽了数据库,而采用面向对象的实体类来表示表关系。 包含关系,继承关系。

分析步骤:

  1. 明确表关系
  2. 确定表关系(描述 外键|中间表)
  3. 编写实体类,再实体类中描述表关系(包含关系)
  4. 配置映射关系

# 多表操作

关于评论

评论前请填好“昵称”、“邮箱”这两栏内容,否则不会收到回复,谢谢!