1. JPA的主键生成策略
1.1 什么是主键
唯一标识 每一行的数据 比如 id =1
主键特点:非空且唯一
主键分类:
代理主键 :没有实际意义的一些列作为主键 比如id 现在就用的代理主键
自然主键 :具体实际意义的列作为的主键 比如 身份证号
1.2 JPA主键生成策略
配置
@Id
@GeneratedValue
private Long id;
GeneratedValue:默认使用 等效于(strategy = GenerationType.AUTO)
自己会根据你的配置的方言 来选择使用的生成策略 – 主键自增mysql --序列(oracle)
--常用方式
@GeneratedValue(strategy = GenerationType.IDENTITY) -- 就是主键自增策略
@GeneratedValue(strategy = GenerationType.SEQUENCE) --序列 mysql不支持 但是oracle支持(不用)
@GeneratedValue(strategy = GenerationType.TABLE) --表的策略 兼容好 可以mysql 支持oracle 性能有点低
@GeneratedValue(strategy = GenerationType.AUTO) -- 默认根据方言来选择
hibernate底层还很多生成策略
搜索内容:两次shift
JPA提供四种生成策略,我们常用是auto
注意事项:如果使用@GeneratedValue ,在保存数据 就不要设置id的值,应该id这个主键值已经交给jpa进行维护
2 JPA的实体状态
JPA有哪些状态?
刚才使用JPA的实体,它其实是有状态的
(1)瞬时状态
刚刚new 创建出来,没有和entityManager发生关系
(2)托管状态(持久状态)
已经和entityManager发生关系
(3)脱管状态(游离状态)
已经和entityManager脱离关系
(4)删除状态
如果我们要删除一个内容 remove 这个对象的状态就是删除状态
2.1脏数据更新 --允许存在
一个持久化状态的数据,如果修改非主键的值,在commit的时候,会自动发送update语句更新
**2.2 n-to-n问题 **
持久化状态的主键 的值 如果被修改问题 – 尽量的不要修改的主键的值
2.3实体定义规则
(1)实体类不能定义成final类型 --最终 不能被继承* 后面讲 lazyload 在使用懒加载的时候,会在内存里面创建一个子类*
(2)实体里面的字段 全部包装类型 底层很多代码都是判断 是否为null**
(3)如果实体里面有有参数的构造方法,一定要提供一个无参数构造方法 比如使用find,要使用无参数的构造方法创建对象
实体(对象)和实体(对象)之间它是有关系的
3 实体之间关系
3.1有哪些关系
(1)依赖关系
依赖注入DI:把对象注入到类里面这个过程 就叫依赖注入 (IOC控制反转)
(2)关联关系(jpa难点)
按照内容或者性质来分:
类和类之间有关联性 比如 员工和部门 多对一
一对多 :一个老师对应多个学生
多对多 : 一个角色(演员 学生 老师) 对应多个权限 ,一个权限 被多个角色管理
一对一:一夫一妻 一个人对应一个身份证 一个qq号 对应一个qq空间
按照导航性分:
单向:只能从一方获取另外一个方 单恋 暗恋
双向:相互都可以获取 热恋
单向 多对一
(3)组合关系:(多对一 或者一对多 整体和部分之间,整体和部分不能分割)
人 和 人的部位
在项目:比如涉及单据的地方 订单
强哥:娃娃 日用品 等 -->订单
(4)聚合关系:(多对一 或者一对多 整体和部分之间,整体和部分可以分开存在)
电脑台式机 鼠标 硬盘 风扇
泛化关系:体现继承
3.2 单向多对一
例如: 产品和产品分类
(1)创建domain 或者实体对象 并且配置
Product
@Entity
@Table(name="t_product")
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
//配置
@ManyToOne
@JoinColumn(name="dir_id")//外键
private ProductDir dir ;
ProductDir
@Entity
@Table(name="t_productDir")
public class ProductDir {
@Id
@GeneratedValue
private Long id;
private String name;
(3)测试
保存:先保存一方 在保存多方 – 好一点 推荐
先保存多方 在保存一方 --多发送sql 去更新外键值
3.3 查询-抓取策略
抓取策略 fetch:
就是告诉jpa使用什么方式去获取的数据
如果我们要使用抓取策略 --在做配置
@ManyToOne(fetch = FetchType.EAGER/LAZY)
EAGER:急切 迫切 你不管你使用不使用 都把数据查询出来
LAZY:懒加载 你需要用的 才去加载数据 性能要好一点
@JoinColumn(name="dir_id")//外键
延迟加载:
掌握配置
(1)延迟加载配置 :@ManyToOne(fetch = FetchType.LAZY)--掌握配置
(2)实体类不要定义成final类型 --注意
推荐使用延迟加载 ,性能要高一点
4 二级缓存
4.1 回顾一级缓存
什么是缓存:
把数据下载到本地 – 看小电影
程序里面:
先从数据库把数据查询出来,放入缓存里面(内存Map),下来查询数据的时候,先从缓存里找,如果有,直接取出,如果没有,在发送sql查询数据,放入缓存
目的:提高查询效率
一级缓存命中条件是什么:
同一个EntityManagerFactory 同一个EntityManager 同一个OID
4.2 二级缓存
一级缓存 是框架自带的缓存,不用做任何配置,就可以使用,它是属于entitymanager级别上面的缓存
二级缓存 是不是框架自带的,需要做配置,才能使用,它是属于EntityManagerFactory级别
二级缓存 也有命中条件:
同一个EntityManagerFactory 不同EntityManager 同一个OID
4.3二级缓存使用
(1)导包
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.8.Final</version>
</dependency>
(2)配置 --底层ehcache这个框架完成
在perisistenc.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" />
扫描策略
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
(4)测试
5 缓存理论
(1)读取大于修改(查询居多 修改很少)
如果经常修改数据,缓存里面数据也需要修改 ,也要同步
(2) 你要对数据 有独享控制,不能被第三方程序改变,不然数据就会出现脏数据
(3) 这个数据必须能够容忍一些错误,太精确的数据不适合放入缓存(金额)
日志信息
(4)缓存数据量不要超过内存容器,超过不能存下来,但是有NB框架,实现钝化的效果
内存数据量满了之后,会存入磁盘 – ehcahe
5.2 缓存命中条件
一级命中条件: --底层自动会用 不用做任何配置
同一个EntityManagerFactory 同一个EntityManager 同一个OID
二级缓存命中: 需要开启二级缓存 做配置 – 选择
同一个EntityManagerFactory 不同的EntityManager 同一个OID
查询缓存命中条件:
同一个EntityManagerFactory 不同的EntityManager 发出jpql语句相同,条件值相同 – 用的很少,
条件值相同情况下 很少,命中很低