jpa笔记

ORM思想

主要目的:操作实体类就相当于操作数据库表

建立两个映射关系:

     实体类和表的映射关系

实体类中属性与表中字段的映射关系

不再重点关注:sql语句

JPA规范

jpa规范,实现jpa规范,内部是由接口和抽象类组成

实体类

配置映射关系:

      1. 实体类和表的映射关系
      2. 实体类中属性和表中字段的映射关系

@Id :声明主键的配置

@Generated:配置主键的生成策略

strategy  

GenerationType.IDENTITY:自增

            *底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)

GenerationType.SEQUENCE:序列,Oracle

            *底层数据库必须支持序列

GenerationType.Table : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增

GenerationType.AUTO: 有程序自动的帮助我们选择主键生成策略

@Column(columnDefinition = "int8")

           name:数据库表中字段的名称

           columnDefinition:

@Entity //声明实体类 
@Table //配置实体类和表的映射关系 //name:配置数据库表的名称 
@Table(name = "stdent")

package com.oceanPlatform.inner.cargo.entity; 
import io.swagger.annotations.ApiModel; 
import io.swagger.annotations.ApiModelProperty; 
import lombok.Data; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.Table; 


@Entity 
@Data 
@ApiModel(value = "student对象", description = "学生信息表") 
@Table(name = "student") 
public class StudentEntity { 
/** 
* @Id声明主键的配置 
* @Generated(strategy = GenerationType.IDENTITY):配置主键的生成策略(自增) * @Column(columnDefinition = "int8") 
* name:数据库表中字段的名称 * columnDefinition: 
**/ 
@Id 
@ApiModelProperty(value = "主键") 
@Column(columnDefinition = "int8") 
private Long id; 
@ApiModelProperty(value = "附件路径") 
@Column(columnDefinition = "varchar(255)") 
private String file; 
 
}

延迟加载(懒加载)getReference() 常用

              得到的是一个动态代理对象

              什么时候用,什么时候才会查询

立即加载 fine

SpringDataJpa

  1. 搭建环境

创建工程导入坐标

配置spring的配置文件

编写实体类,使用jpa注解配置映射关系

<!-- 数据库驱动--> 
spring.datasource.driver-class-name=org.postgresql.Driver 
<!-- 数据库连接--> 
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/post spring.datasource.username=postgres spring.datasource.password=postgres 
<!-- --> 
spring.jpa.hibernate.ddl-auto=update 
<!-- 是否显示SQL--> 
spring.jpa.show-sql=false 
<!-- 数据库方言:支持的特有语法--> 
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL9Dialect spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
      1. 编写一个符合springDataJpa的Dao 层接口

Dao层接口规范

    需要继承两个接口(JpaRepository,JpaSpecificationExecutor

    需要提供相应的泛型

JpaRepository

     封装了基本的CRUD(增删改查)操作

JpaSpecificationExecutor

    封装了复杂查询(分页)

@Repository 
public interface StudentRepository extends JpaRepository<StudentEntity, Long>, JpaSpecificationExecutor { 
@Modifying 
@Query(value = "delete FROM student where id = ?1",nativeQuery = true) 
void deleteAllById(long id); 
Integer countById(Long id); 
}

save: 保存或者更新

    根据传递的对象是否存在主键id

    如果没有id主键属性,保存

    存在id主键,根据id查询数据库,更新数据

simpleJpaRepository

      实现了JpaRepository接口,实现了JpaSpecificationExecutor接口

      对基本的增删改查操作进行了封装

springdataJpa的运行过程和原理剖析

    1. 通过JDKDynamicAopProxy的invoke方法创建了一个动态代理对象
    2. SimpleJpaRepository当中封装了JPA的操作(借助JPA的api完成数据库的CRUD)
    3. 通过hibernate完成数据库操作(封装了jdbc)

@Transactional:保证getOne正常运行

findOne 与getOne

  findOne:

     em.find() :立即加载

getOne:

     em.getReference() :延迟加载

复杂查询

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

findOne(id):根据id查询

  1. jpql的查询方式

jpql:jpa query language(jpa查询语言)

  特点:语法或关键字和SQL语句类似

  查询的是类和类中的属性

  需要将JPQL语句配置到接口方法上

    1. 特有的查询:需要在dao接口上配置方法
    2. 在新添加的方法上,使用注解的形式配置jpql查询语句
    3. 注解: @Query

代表的是进行查询

声明此方法用来进行更新操作

@Transactional 
@Modifying 
@Query(value = "update StudentEntity s set s.Stat = false where s.id = :id") 

方法名约定:

   findBy:查询

         对象中的属性名(首字母大写);查询条件

         findByStudentName 根据学生名查询

         默认情况,使用 等于的方式查询

特殊的查询方式

在springdataJpa的运行阶段

会根据方法名进行解析 findBy from xxx(实体类)

属性名称 where studentName

Specifications动态查询

Specification:查询条件

   实现Specification接口(提供泛型:查询的对象类型)

   实现toPredicate方法(构造查询条件)

   需要借助方法参数中的两个参数(

root:获取需要查询的两个参数

criteriaQuery

criteriaBuilder:构造查询条件,内部封装了很多的查询条件(模糊匹配,精准匹配)

equal :直接得到path对象(属性),然后进行比较即可

gt, lt, ge, like:得到path对象,然后根据path指定比较的参数类型,再去比较

指定参数类型,path.as(类型的字节码对象)

//分页参数设置 
Pageable pageable = PageRequest.of(pagination.getCurrent() - 1, pagination.getPagesize(), sort);

private Specification<StudentEntity> queryCondition(StudentSearchModel queryModel) { return (Specification<StudentEntity>) (root, criteriaQuery, criteriaBuilder) -> { List<Predicate> predicates = new ArrayList<>(); 
//学号查询 equal:进行精准匹配(比较的属性,比较的属性的取值) 
if (!StringUtils.isEmpty(queryModel.getStudentId())) { predicates.add(criteriaBuilder.equal(root.get("studentId"), queryModel.getStudentId())); } 
//root.get("studentId") 获取属性 
//学期开始查询
if (!StringUtils.isEmpty(queryModel.getTermStartDate())) { predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("termStartDate"), queryModel.getTermStartDate())); 
} 
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); 
}; 
}

多表查询:

多表之间的关系和操作多表的操作步骤

表关系

一对一

一对多

一的一方:主表

多的一方:从表

外键:需要再从表上新建一列作为外键,它的取值来源于主表的主键

多对多

中间表:中间表中最少应该有两个字段组成,这两个字段作为外键指向两张表的主键,又组成了联合主键

实力类中的关系:

包含关系:可以通过实体类中的包含关系描述表关系

继承关系

  1. 一对一操作
  1. 多对多操作

配置一对多关系

//@Fetch(FetchMode.JOIN) 
 @OrderBy("sort ASC") 
//CascadeType.PERSIST:级联新增(又称级联保存) 
 @OneToMany(cascade=CascadeType.ALL,orphanRemoval = 
 true,fetch=FetchType.LAZY,mappedBy="voyageId") 
 @NotFound(action = NotFoundAction.IGNORE) 
 private List<StudentEntity> studentEntities;

使用注解的形式配置多表关系

  1. 声明关系

@OnetoMany:配置一对多关系

  targetEntity:对方对象的字节码对象

  mappedBy="studentId":我的一对多映射参照对方属性,在一的一方放弃了外键的维护权

  fetch=FetchType.EAGER:立即加载

  fetch=FetchType.LAZY:延迟加载

  配置外键(中间表)

  @JoinColum:配置外键

  name: 外键字段名称

  referencedColumnName: 参照的主表的主键字段名称

@ManyToOne(fetch=FetchType.EAGER) 
@JoinColumn(name="class_id")
//student_id字段作为外键 
@ApiModelProperty(value = "班级id") 
private ClassEntity classId;

级联

操作一个对象的同时操作他的关联对象

级联添加

案例:当我保存一个客户的同时保存他的联系人

级联删除

案例:当我删除一个客户的同时删除他的联系人

@ManyToMany

@ManyToMany(fetch = FetchType.LAZY) 
@JoinTable(name = "rp_role_menu",
//设置中间表的名字,以及中间表的字段名 
          joinColumns = {@JoinColumn(name="roleId")},//joinColumns, 当前对象在中间表中的外键 
          inverseJoinColumns = @JoinColumn(name="menuId")//inverseJoinColumns, 对方对象在中间表的外键

希望以上笔记会对你对jpa学习提供帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值