JPA 02 进阶

JPA 02 进阶

主键生成策略(掌握);

​ 主键:能够区分表里面每一行数据

​ 主键特点:非空且唯一

​ 主键的分类:

​ 自然主键:具有实际意义的列来作为主键

代理主键:没有实际意义的列来作为主键 — 单个项目使用

JPA直接不定义 @GeneratedValue 就可以了,在保存之前设置主键的值

如果定义看 @GeneratedValue ,再去设置主键的值就会报错 不能修改主键值

​ 什么是主键的生成策略

​ JPA采取的方案方式去生成主键;

​ JPA主键生成策略:

auto策略: – 默认使用给这种: 根据数据库的方言来选择到底使用哪种策略(常用的)

​ 比如 配置Mysql的方言 – 策略, 自增策略

​ 配置oracle的方言 – 序列sequence策略

table策略:表的生成策略 额外创建一张表来维护

counttable_name
1t_employee

sequeence策略:序列策略

identity策略:mysql采用这种自增策略

Hibernate内置主键生成策略的定义:

在这个类里面 org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory

 public DefaultIdentifierGeneratorFactory() {
        this.register("uuid2", UUIDGenerator.class);
        this.register("guid", GUIDGenerator.class);
        this.register("uuid", UUIDHexGenerator.class);
        this.register("uuid.hex", UUIDHexGenerator.class);
        this.register("hilo", TableHiLoGenerator.class);
        this.register("assigned", Assigned.class);
        this.register("identity", IdentityGenerator.class);
        this.register("select", SelectGenerator.class);
        this.register("sequence", SequenceGenerator.class);
        this.register("seqhilo", SequenceHiLoGenerator.class);
        this.register("increment", IncrementGenerator.class);
        this.register("foreign", ForeignGenerator.class);
        this.register("sequence-identity", SequenceIdentityGenerator.class);
        this.register("enhanced-sequence", SequenceStyleGenerator.class);
        this.register("enhanced-table", TableGenerator.class);
    }

Hibernate是实现了JPA接口的主键生成策略, Hibernate和JPA主键生成策略是一样的,没有区别,JPA就是 Hibernate的规范。

JPA持久对象的状态(掌握);

一个实体交给JPA维护的时候,这个实体在不同的时期,状态不一样

临时(瞬时)状态:刚刚创建出来,没有和JPA进行发生关系

持久(托管)状态:这个实体对象已经和JPA发生关系

游离(脱管)状态:脱离entityManager的管理,已经被持久化,不存在entityManager里面

删除状态:即将要删除的时候,remove,还没有提交事务

entityManager的方法改变持久对象的状态
在这里插入图片描述
图解:四大状态

new:瞬时状态

Mnagerd:持久状态

commit . clear :游离状态

removed: 删除状态

脏数据更新 :

一个持久化状态的数据,如果修改的非主键的数据之后,在commit的时候,自动会去发送update语句更新,底层通过缓存来操作的

所以要 clear一下 清理缓存

如果一个持久化数据,改变了主键的值 —会报错 报错 n-to-n的错误,持久化状态的数据

实体的类定义规则

​ 1.类不要定义成final 否则延迟加载会受影响;

​ 2.实体里面属性的类型定义成包装类型,很多底层代码都是通过判断是否为null

​ 3.实体里面有默认无参的构造方法

域对象之间的关系;

对象和对象之间,存在一定关系

​ 存在什么关系?

依赖关系:

​ 一个类去依赖另外一个类,比如Service层Dao层 —> 依赖注入(DI)spring

关联关系:

​ 一个类和另外一个类他们之间是有关系的;

​ 比如员工和部门 — 多对一 — 一对多— 多对多 — 一对一

聚合关系:

​ 整体和部分的关系,整体和部分可以分开存在

组合关系:

​ 也是整体和部分的关系,整体和部分是不可以分开存在的

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

1.类不能定义为final类

因为domain类需要被继承的,否则延迟加载会失效

而且final的类无法产生子类

2.所有属性的类型都必须是包装类型

不能是8个基本类型(int,byte,short,long,char,boolean,float,double)

因为JPA内部代码很多判断都是基于是否等于null

3.必须有默认无参构造方法

因为find方法获取的时候会在内存实例化domain对象

否则报org.hibernate.InstantiationException: No default constructor for entity异常

如果只有有参的构造方法默认的无参构造方法就会消失,就会报错,所以必须在再写一个无参的构造方法(底层通过反射 通过无参构造方法创建对象)

脏数据更新: 一个持久化状态数据,修改非主键的值,会在commit提交的时候自动发送sql

**n-to-n问题:**一个持久化状态数据,如果修改主键的之后,就会报错,也就是说持久化状态的数据,不能改变主键值!

单向多对一(重点掌握);

单向就是java的一个类Product可以获取另一个类ProductDir

@ManyToOne 多对一

@JoinColumn(name=“dir_id”) @JoinColumn指定外键ID

//方产品类型
public class ProductDir {
  @Id
  @GeneratedValue
  private Long id;
  private String name;

//多方产品
@Entity
public class Product {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  // 多Product对一ProductDir
  // 多个产品属于一个产品类型
  // 外键在那个表,这个表就是多
  @ManyToOne(fetch = FetchType.LAZY) // 实现延迟加载
  // @ManyToOne(fetch = FetchType.EAGER) // 默认值,左外连接查询
  // JoinColum设置了外键的名字,不配置默认一方属性名_id
  // @JoinColumn(name = "dir_id")
  private ProductDir dir;

二级缓存(掌握);

​ 一级缓存:属于EntityManager级别的缓存,他是自带的

​ 命中条件:

​ 同一个EntityManagerFactory 同一个EntityManager同一个OID

​ 二级缓存:

​ 属于EntityManagerFactory级别缓存,它不是自带(可以用可以不用),

如果要使用二级缓存,相应配置之后,才能使用二级缓存 ------ 通过Encache(缓存框架)框架来实现二级缓存

/*
	第一步
    先在Pom.xml里面配置
    <!--二级缓存的jar包-->
*/
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-ehcache</artifactId>
      <version>4.3.8.Final</version>
    </dependency>
    
     
//  第二步: 二级缓存配置  添加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" />
    
/*   第三步
在<properties>上面添加配置二级缓存扫描的策略
<!-- ALL:所有的实体类都被缓存 -->
<!-- NONE:所有的实体类都不被缓存. -->
<!-- ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存 -->
<!-- DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类 -->
<!-- UNSPECIFIED:默认值,JPA 产品默认值将被使用 -->
*/
 // ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存 
 <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

    
    
 
二级缓存命中条件:同一个entityManagerFactory,不同的entityManager,OID相同
// 一条sql
// @Entity
// @Cacheable(true)
// public class Department
@Test
public void test2() throws Exception {
	EntityManager entityManager = JPAUtils.getEntityManager();
	//先从一级缓存,二级缓存取数据?取不到,发出sql去获取,填充一级缓存,二级缓存
	Department department1 = entityManager.find(Department.class, 1L);
	//先从一级缓存,二级缓存取数据?一级缓存取到了,返回
	Department department2 = entityManager.find(Department.class, 1L);// 一级缓存命中
	entityManager.close();

	EntityManager entityManager2 = JPAUtils.getEntityManager();
	//先从一级缓存,二级缓存取数据?一级缓存没有取到,但是二级缓存取到了,返回
	Department department3 = entityManager2.find(Department.class, 1L);// 二级缓存命中
	//先从一级缓存,二级缓存取数据?一级缓存取到了,返回
	Department department4 = entityManager2.find(Department.class, 1L);// 一级缓存命中
	entityManager2.close();
}
       
    
 



    
查询缓存:依赖于二级缓存  如果查询缓存有查询条件,就不要使用查询缓存,因为命中率非常低 基本上不用
// 一条sql
// 命中条件:同一个EntityManagerFactory,不同一个entityManager,发出的sql语句必须相同并且查询的条件值也要相同
// 1.如果查询缓存有查询条件,就不要使用查询缓存,因为命中率非常低
// 2.查询缓存里面查询指的是使用jpql,sql进行的查询,就是调用了createQuery方法,find方法不是走查询缓存
// 3.进行domain类的二级缓存的配置
// @Cacheable
// public class Employee {


JPA抓取策略:

JPA告诉程序员使用哪种方式去获取数据
抓取策略配置:
@ManyToOne(fetch = FetchType.LAZY)  //懒加载抓取  需要使用的时候,才发送sql查询
//懒加载(lazyload)会默认生成一个 子类。 ---- 底层代理模式
"类千万一定不要定义成 final,不然懒加载会失效,因为定义为final的类是太监类 无法有子类,所以懒加载底层的代理模式就无法生成子类,虽然不会报错,但是懒加载会失效"
@ManyToOne(fetch = FetchType.EAGER) //迫切加载  --默认为迫切加载-- 不使用都把数据加载出来,发送左外连接查询数据
----占用内存

缓存理论

什么情况下使用二级缓存(掌握)

(1)读取大于修改的使用 --查询居多的时候使用二级缓存

(2)对数据要有独享的控制,不能被第三方程序修改

(3)可以容忍一些无效数据,非关键性数据(财务金额不适合放入缓存里面)

​ 日志信息

(4)如果数据大于内存,不适合放入缓存里面 – 钝化

​ 内存100M 数据500M

ehcache支持钝化

http://www.mamicode.com/info-detail-1291774.html

缓存淘汰策略:

LRU(Least Recently Used):最近最少使用 --> 时间为参考点
LFU(Least Frequently Uesd):最不经常使用 -->次数为参考点
FIFO(First in First Out):先进先出 quene

缓存命中条件(掌握)

一级缓存:自带

​ 同一个EntityManagerFactory 同一个EntityManager 同一个OID

二级缓存: 需要配置才能实现

​ 同一个EntityManagerFactory 不同EntityManager 同一个OID

查询缓存:依赖二级缓存

​ 同一个EntityManagerFactory 不同EntityManager 相同jpql 和条件相同

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值