zoukankan      html  css  js  c++  java
  • SpringData JPA

    SpringData JPA

    JPA是规范:本质上是一种ORM规范,不是框架。

    SpringData JPA是封装基于jpa规范的一套应用框架。

    1. findOne(long id)
    2. sava(eneity)
    3. findAll(long id)
    4. delete(long id)

    实现原理:

    通过动态代理的方式,自动生成代理对象。

    1. 通过JdkDynamicAopProxy的invoke方法创建动态代理实现
    2. SimpleJpaRepository当中封装了JPA的操作(基本crud)
    3. 通过hibernate完成数据库操作。

    复杂查询:

    1. 借助接口中定义好的查询方法。

      1. count() 统计总条数
      2. boolean exists(long id)
      3. findOne 立即加载 与 方法,延迟加载。
    2. 使用jpql查询。在实体类的属性上添加@Query
      @Query(value=“from user where name=?”)
      public User getUser(String name) ;

      • 有多个占位数参数,默认情况下,占位符的位置需要和方法中的参数位置保持一致
      • 也可以指定参数的位置 ?索引的方式 指定取参数中第几个值。
      • @Modifying 声明这是个更新参数。
      • 进行更新或删除操作时,需要添加事务和设置不回滚操作。
    3. SQL查询

      1. @Query 中value:jpql语句 | sql语句
      2. nativeQuery=true 代表sql查询。 false jpql查询
    4. 方法名称规则查询,是对jpql查询更加深入的封装。

      1. findBy查询(对象的属性名首字母大写) 例如 findByCustName
      2. 模糊查询 findBy+实体类属性名+查询方式 (like|isnull) findByCustNameLike
      3. 多条件查询 findBy+实体类属性名+查询方式 (like|isnull)+连接符(and|or)+属性名+查询方式 (like|isnull) findByCustNameLikeAndCustIdustry()

    自定义查询条件:

    1. 实现specification接口(提供泛型)
    2. 实现toPredicate方法(构造查询条件)
    3. 借助方法中的两个参数
      1. root 获取 查询对象的属性
      2. CriteriaBuilder:构造查询条件的,内部封装了很多查询条件(模糊匹配,精准匹配)

    分页:

    使用Pageable接口,pageRequest实现类 ,使用构造方法创建

    第一个参数,查询当前页的页数,第二个参数,煤业查询的数量。

    page.getContent();//得到内容数据集合列表
    
    page.getTotalElements();//得到总条数
    
    page.getTotalPages();//得到总页数
    

    多表查询

    表关系:

    • 一对一
    • 一对多
      • 一的一方:主表
      • 多的一方:从表
      • 外键:需要在从表上建立一列作为外键,值为主表的主键
    • 多对多
      • 中间表:至少两个字段组成,这两个字段作为外键指向两张表的主键,又组成联合主键。

    1、一对多

    老师对学生:一对多

    实体类的关系:

    包含关系:通过实体类的包含关系来描述表关系

    继承关系

    分析步骤:

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

    客户和联系人之前的关系:一对多

    • 客户实体类:相对于本身,一对多,使用集合保存联系人,推荐使用Set

    使用@OneToMany(targetEntity = linkMan.class)

    targetEntity :对方的字节码对象

    @JoinColumn配置外键

    	name:外键字段名称   referenceColumnName参照主表的主键字段名称
    

    需要在1的一方,添加了外键的配置,所以对客户而言,也具备了维护外键的作用。

    @OneToMany(targetEntity = linkMan.class)
    @JoinColumn(name="从表表示外键的字段",referenceColumnName="主表的主键")
    private Set<LinkMan> linkMans
    
    • 联系人实体类:相对于本身,多对一,实体类中包含了客户的对象。

      @ManyToOne(targetEntity = Customer.class)
      @JoinColumn(name="从表 表示外键的字段",referenceColumnName="主表的主键")
      private Customer customer

    当两边都配置外键关系时,是双向外键维护。

    一的一方,会多执行一条update语句维护外键。

    多的一方,会直接在insert中维护外键。

    双向绑定会多执行一条update语句,如果不需要执行,那么一的一端需要主动放弃外键维护权。

    mappedBy:对方配置关系的属性名称

    @OneToMany(mappedBy = "customer")
    private Set<LinkMan> linkMans
    

    一对多的删除

    删除主表数据时

    • 当从表有数据
    1. 在默认情况,会把外键字段置为null,然后删除主表数据,如果从表外键字段有非空约束,默认情况就会报错。
    2. 如果配置了放弃维护关联关系的权力,则不能删除,因为在删除时,根本不会去更行从表的字段
    3. 如果还想删除,使用级联删除引用。

    级联

    操作对象的同时,同时操作他的关联对象。

    级联操作:

    1. 需要区分操作主体
    2. 需要在操作的主体的实体上,添加级联属性
    3. cascade(配置级联)

    级联添加

    保存一个客户的同时,保存客户的所有联系人

    需要在操作主体的实体上,配置casacde属性

    ALL:所有

    MERGE :更新

    PERSIST:保存

    REMOVE:删除

    @OneToMany(mappedBy = "customer" cascade=CascadeType.ALL)
    private Set<LinkMan> linkMans
    

    级联删除

    删除1号客户的同时,删除1号客户的所有联系人。

    2、多对多

    案例:用户和角色

    	用户:用户有很多角色
    
    	角色:角色可分配给多个用户
    

    配置多对多的映射关系

    1. 申明表关系的配置

      1. @ManyToMany(targetEntity = Role.class) //多对多
    2. 配置中间表

      //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(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 Set users = 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<Role> roles = new HashSet<>();
    
    
    
    //Role.java
    @ManyToMany(mappedBy = "roles")
    private Set<User> users = new HashSet<>();
    

    级联

    多对多支持级联

    多表的查询

    1. 对象导航查询
      查询一个对象的同时,通过此对象查询他的关联对象。
      默认使用延迟加载的方式查询,调用get方法不会立即发送查询,而是在使用关联对象的时候才会出现查询。
      不使用延迟加载,需要配置。
      fetch ,需要配置到多表映射关系的注解上。EAGER 立即加载 LAZY延迟加载

      @ManyToMany(mappedBy = "roles" , fetch = FetchType.EAGER)

    EAGER 立即加载 底层实现,通过连表(left join)的方式实现,不推荐立即查询

    一对多中 从多的一方查询,默认使用立即加载。将其中1的一方一起查询出来。

    从一表查询多方

    *默认:使用延迟加载。
    

    多方查询一方

    *默认使用:立即加载。
  • 相关阅读:
    DataGirdView 编辑项时的验证
    存储过程分面
    Android PopupWindow菜单
    Android ListView 中的checkbox
    Linq Group
    final关键字
    BroadcastReceiver
    Android Studio 快捷键
    Android Studio 基础知识
    黑客帝国代码雨实现
  • 原文地址:https://www.cnblogs.com/xiaolaodi1999/p/14185301.html
Copyright © 2011-2022 走看看