JPA进阶与二级缓存

主键生成策略

主键设置两种方式
  • 代理主键(没有业务含义,建议使用)
  • 自然主键(有业务含义:手机号,身份证,…)
四种主键生成策略

IDENTITY:自增策略:

  • 大多数数据库支持IDENTITY,即在数据库表中配置AUTO_INCREMENT,在插入新行时就可以实现主键自增
  • 支持的数据库:MySQL, SQL Server, DB2, Derby, Sybase, PostgreSQL
  • 效率高

SEQUENCE:序列策略

  • Oracle是不支持IDENTITY的,它依靠序列机制来生成主键
  • 在Mysql中设置的AUTO_INCREMENT是针对这张表的对不对,而oracle一个序列可以提供给多个表使用,用在分表场景中
  • 支持的数据库:Oracle、PostgreSQL、DB2
  • 效率高

AUTO:自动(默认)

  • 默认就是它
  • 将选择权交给JPA,JPA根据方言中的配置来选择主键生成策略

在这里插入图片描述
在这里插入图片描述
Table:表策略

  • 在数据库中建议张序列表来生成具体主键
  • 不依赖数据库具体实现,增加移植性
  • 本质是用普通表来模拟序列

对应的状态

  • 临时状态:指该对象刚刚被创建出来的时候,任何对象都有这个过程
  • 持久状态:对象和em发生关系(一级缓存中)
  • 游离状态:em.close em.clear都会解除em和持久对象之间的关系,这时候持久对象就成了游离对象
  • 删除状态:em.remove
快照与一级缓存

快照也是一级缓存(即session作用域),em对象调用persist或者merge等方法时(此时还没有commit),session向数据库发送select语句进行查询,会将查询结果返回给session(以后当一级缓存有值就不用再查数据库了),session将结果分成拉两份,一份存在缓存,另一份就为快照。
当提交事务时(commit),如果发现一级缓存与快照内容不一致,会向数据库发送update语句,没变化就不发
JPA进阶与二级缓存_第1张图片
JPA进阶与二级缓存_第2张图片
在上面的代码中,如果在第一个commit后面加上clear,就会清空一级缓存,这时候就会重新查询数据库了,即有两条sql语句了,你也可以将merge返回的两个对象的哈希吗进行比较,他们也是相同的。

merge与remove

merge:负责将一个临时状态的对象转换为持久化状态对象,它会返回一个持久化对象。
remove:它将持久化对象转换成删除状态
remove为什么要传递对象:因为你只能使用find或者merge返回的对象,只有这些对象才是持久化状态对象,你用new的话是临时状态,不能用,同时游离状态也不能用。

对象之间的关系

多重性
  • 一对一 (共享主键,唯一的外键【建议】)
  • 多对一 (有外键关系,外键在哪边,哪边就是多方)
  • 一对多 (同上)
  • 多对多 (中间表)
  • 表有多重性没有导航性
导航性
  • 单向与双向
  • 只用于类(对象),和表没有关系
组合与聚合

组合用于两个不可分割的对象
聚合可以拆分,但只限于一对多、多对一,无法用于多对多

单向多对一的配置

Student:

@Entity
public class Student {
     
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    // 默认是EAGER
    @ManyToOne(fetch = FetchType.LAZY)
    // 外键名,会调用Teacher的set方法
    @JoinColumn(name = "teacher_id")
    private Teacher teacher;
    public void setTeacher(Teacher teacher) {
     
        this.teacher = teacher;
    }
    public Student() {
     
    }
}

Teacher:

@Entity
public class Teacher {
     
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    public Teacher(String name) {
     
        this.name = name;
    }
    public Teacher() {
     
    }
    @Override
    public String toString() {
     
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

测试:

@Test
    public void testMany2One() {
     
        Student student = new Student();
        Teacher teacher = new Teacher();
        // 先设置一,在设置多
        teacher.setName("张老师");
        student.setName("张同学");
        student.setTeacher(teacher);
        EntityManager em = JpaUtil.getEm();
        em.getTransaction().begin();
        em.persist(teacher);
        em.persist(student);
        em.getTransaction().commit();
        em.close();
    }

FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。
FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

二级缓存

  • 一级缓存命中:同一个EntityManagerFactory,同一个EntityManager,同一个OID
    JPA进阶与二级缓存_第3张图片
  • 二级缓存命中:同一个EntityManagerFactory,不同EntityManager,同一个OID
什么情况可以使用二级缓存
  • 经常被查询,但是很少修改
  • 数据不能被第三方修改
  • 不能是敏感数据
  • 缓存量不能太大

你可能感兴趣的:(JPA)