JAVA学习笔记:JPA进阶&二级缓存

本文详细介绍了JPA中的主键生成策略,包括auto、table、sequence和identity策略,并探讨了主键的分类。接着讲解了JPA持久对象的状态及其管理,特别是脏数据更新和n-to-n问题。此外,文章还涵盖了域对象间的关系、单向多对一映射、JPA抓取策略和二级缓存的使用,包括何时使用、配置、淘汰策略和缓存命中条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.JPA主键生成策略

1.1 概念

主键是关系型数据库中的一个基本概念,它用来保证记录的唯一性。同一个表中,不允许存在多条相同主键的记录。简单的说就是具有自增、非空且唯一的特性。

1.2 JPA标准主键生成策略

  1. auto:自动根据方言来选择表主键生成(默认)
  2. table:表的生成策略,会另外创建一张表来维护主键,兼容性比较好 性能麻烦(一般不用)
  3. sequence:序列策略
  4. identity:自增策略

1.3 主键的分类

自然主键:具有实际业务意义的列作为为主键,比如身份证号码
代理主键:没有实际意义的列作为主键,比如 id(推荐)

2. JPA持久对象的状态

2.1 JPA的状态

新建状态、临时状态、瞬时状态:刚刚创建出来的对象,还没有和EntityManager发生关系;
持久状态、托管状态:和EntityManager发生关系、比如调用persist merge等方法;
游离状态、脱管状态:脱离EntityManager管理,比如clear,close,commit提交之后
删除状态:计划要准备删除的时候,remove之后

2.2 脏数据更新及n-to-n问题

如果一个持久化状态的数据,改变非主键的值,在提交的时候,自动发送sql语句更新
如果一个持久化状态的数据,改变主键的之后,报错 n-to-n的错误
org.hibernate.HibernateException: identifier of an instance of xxx was altered from 1 to 200
如果一个非持久化状态的数据 ,就可以改变

2.3 持久对象(domain层)定义规则

  1. 类不能定义为final类
    因为domain类需要被继承的,否则延迟加载会受到影响
  2. 所有属性的类型都必须是包装类型
    不能是8个基本类型(int,byte,short,long,char,boolean,float,double)
    因为JPA内部代码很多判断都是基于是否等于null
  3. 必须有默认无参构造方法
    因为find方法获取的时候会在内存实例化domain对象
    否则报org.hibernate.InstantiationException: No default constructor for entity异常

3. 域对象之间关系

3.1 依赖关系

JavaBean之间的依赖关系,比如controller层依赖service层,service层依赖dao层

3.2 关联关系

类与类之间存在关联,比如员工类和部门类,
分为:1对1,1对多,多对1,多对多
按导航性来分:单向和双向

3.3 聚合关系

整体和部分可以分开,单独存在

3.4 组合关系

也叫强聚合关系,整体和部分不可分开

4. 单向多对一

多方类的配置(员工)

@Entity
public class Employee {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name="dept_id") 
    private Department dept;
}

一方配置(部门)

@Entity
public class Department {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}

保存:
必须先保存一方,再保存多方,这样可以少发送sql语句

5. JPA抓取策略

告诉程序用哪种策略去获取数据

  1. 懒加载,需要的时候才去发sql语句获取数据
    @ManyToOne(fetch = FetchType.LAZY )
  2. 迫切加载,先把数据通过左外链接获取出来
    @ManyToOne(fetch = FetchType.EAGER)

6. 二级缓存

6.1 什么时候使用二级缓存

  1. 读取大于修改,因为修改数据的时候,缓存同步变化
  2. 对数据要有独享控制,数据不会被第三方修改;如果修改数据,缓存也需要改变
  3. 缓存里面数据 可以容忍无效数据(日志信息等对实时性要求不高数据)
  4. 如果数据量比较大,也不适合放入缓存(钝化encache 支持内存 磁盘存储)

6.2 二级缓存的使用

  1. 导入jar包
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>4.3.8.Final</version>
</dependency>
  1. 添加persistence.xml配置信息
<!-- 启用二级缓存 -->
<property name="hibernate.cache.use_second_level_cache" value="true" />
<!-- 二级缓存的实现类,文档里面的包名有错的 -->
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
<!-- 启用查询缓存 -->
<property name="hibernate.cache.use_query_cache" value="true" />
  1. 添加配置二级缓存扫描的策略(在上面)
    扫描策略:
    ALL:所有的实体类都被缓存
    NONE:所有的实体类都不被缓存
    ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
    DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
    UNSPECIFIED:默认值,JPA 产品默认值将被使用
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

6.3 缓存淘汰策略

LRU(Least Recently Used):最近最少使用
LFU(Least Frequently Uesd):最不经常使用
FIFO(First in First Out):先进先出

6.4 缓存命中条件

一级缓存:同一个EntityManagerFactory,同一个EntityManager,同一个OID
二级缓存:同一个EntityManagerFactory,不同EntityManager,同一个OID,需要在domain类上面配置@Cacheable(true)
查询缓存:同一个EntityManagerFactory,不同EntityManager,相同jpql和条件的相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值