JPA进阶

1.主键生成 策略【非空且 唯一】
(1) 自然主键:有业务含义的主键
代理主键:这个主键没有意义,用来区别每行的数据是不同的,最常用
(2) auto策略、table策略、sequence策略、identity策略
默认使用这种:根据数据库方言来选择的到底使用哪种策略
​ 比如 配置mysql的方言 --策略 自增策略 (都喜欢mysql)

​配置oracle的方言 -- 策略  序列sequence策略 --很多不用 收费 有钱的公司(金融 保险 政府)
   create sequece s_employe
   insert into table(id,name,...) values(s_employee.nextVal())

2.JPA持久对象【domain】的状态
(1) 临时状态(transient):瞬时状态
刚刚用new语句创建,没有和entityManager发生关系
没有被持久化,不处于entityManager中。该对象成为临时对象
(2) 持久化状态(persistent):托管状态
和entityManager发生关系已经被持久化,加入到entityManager的一级缓存中(填充一级缓存)。
该状态的对象为持久化对象。
(3) 游离状态(detached):脱管状态
已经被持久化,但不处于entityManager中。该状态的对象为游离对象。
(4) 删除状态
只有调用了entityManager.remove(domain对象)方法对象有关联的ID,并且在entityManager管理下, 但是已经被计划删除,事务提交就真的被删除了。
(5) 一个持久化状态数据,修改非主键的值, 会在commit提交的时候,自动会发送sql去更新


	    //Person person = new Person();//临时状态
        //person.setName("狗子");  //临时状态
        EntityManager entityManager = UtilJpa.get();
        entityManager.getTransaction().begin();
        // entityManager.persist(person);  //持久状态
        Person person = entityManager.find(Person.class, 1); //持久状态
        person.setName("大狗子");  //持久化状态的数据,修改非主键的值,自动会发送sql去更新
        entityManager.getTransaction().commit();
        entityManager.close();  //游离状态
        //entityManager.remove();  删除状态

(6) n-to-n问题
持久化的对象不能修改主键,会报错

org.hibernate.HibernateException: identifier of an instance of cn.itsource.jpa.state.StateDomain was altered from 1 to 200

3.域对象之间的关系
(1) 依赖关系
比如 service层去调用 dao层的持久方法 就是依赖关系
Controller表现层依赖于Service业务层,Service依赖于Dao持久层
(2) 关联关系
关联按照多重性可分为一对一、一对多、多对一和多对多。 主要指的数据库(类)的关系
(3) 聚合关系
表示整体与部分的关系,整体和部分可以分开单独存在。
电脑(主板,CPU,IO,内存条)
(4) 组合关系
指的是类与类之间的继承关系设置 Animal --》 Person Pig Cat Bird

4.单向多对一【重点】

@Entity
@Table(name = "t_productdir")
public class ProductDir {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;

    public ProductDir(Integer id) {
        this.id = id;
    }

    public ProductDir() {
    }
------------------------------------------------------------------------------
 两个domain的注解配置详情
@Entity
@Cacheable(true)
@Table(name = "t_product")
public class Product {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    // 多Product对一ProductDir
    // 多个产品属于一个产品类型
    // 外键在那个表,这个表就是多
    @ManyToOne(fetch = FetchType.LAZY) // 实现懒加载
    // @ManyToOne(fetch = FetchType.EAGER) // 实现迫切加载  发送左外连接查询数据
    // JoinColum设置了外键的名字,不配置默认一方属性名_id
    @JoinColumn(name = "dir_id")
    private ProductDir dir;
    
Java代码:一次性保存一方,同时保存2个多方
案例:保存一个产品类型(ProductDir),两个产品(Product)

5.获取对象的加载方式【FetchType.LAZY:延迟加载】【FetchType.EAGER 迫切加载】
(1) 默认情况下,JPA持续性提供程序使用获取类型EAGER:这将要求持续性提供程序运行时必须迫切左外连接获取数据 也就是会查询出多张表的数据
(2) .LAZY:延迟加载 你需要哪个表的数据,就给你查询哪个表的数据

6.二级缓存
(1) 添加依赖的jar包

缓存的命中条件
一级缓存:同一EntityManagerFactory  同一EntityManager   同一OID  【自带的】
二级缓存:同一EntityManagerFactory   不同EntityManager   同一OID  【需要配置】
查询缓存:同一EntityManagerFactory  sql/jpql语句一样    【需要依赖二级缓存】
<dependency>
	    <groupId>org.hibernate</groupId>
	    <artifactId>hibernate-ehcache</artifactId>
	    <version>4.3.8.Final</version>
	</dependency>

(2) 添加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" />
<!-- ALL:所有的实体类都被缓存 -->
<!-- NONE:所有的实体类都不被缓存. -->
<!-- ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存 -->
<!-- DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类 -->
<!-- UNSPECIFIED:默认值,JPA 产品默认值将被使用 -->
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
	使用二级缓存需要在domain中配置  @Cacheable(true) 
@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();
}

7.查询缓存:依赖于二级缓存

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

        EntityManager entityManager = UtilJpa.get();
        String jpql ="select p from Product p where p.id = ?";
        TypedQuery<Product> query = entityManager.createQuery(jpql, Product.class).setParameter(1, 1);
        /* 将查询结果放入到查询缓存*/
        query.setHint(QueryHints.HINT_CACHEABLE, true);
        System.out.println(query.getResultList().size());
        // entityManager.find(Product.class, 3);  //只有一条sql语句,一级缓存命中
        entityManager.close();
        EntityManager entityManager2 = UtilJpa.get();
        String jpql2 ="select p from Product p where p.id = ?";
        TypedQuery<Product> query2 = entityManager2.createQuery(jpql2, Product.class).setParameter(1, 1);
        /* 将查询结果再次放入到缓存中*/
        query2.setHint(QueryHints.HINT_CACHEABLE, true);
        System.out.println(query2.getResultList().size());
        entityManager2.close();
4.缓存淘汰策略:

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

8.什么情况下适合使用二级缓存
(1)读取大于修改的使用 --查询居多的时候使用二级缓存

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

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

​ 日志信息

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

ehcache.xml文件里面属性含义
timeToIdleSeconds="300"秒 timeToLiveSeconds="600" 秒overflowToDisk="true"
/>
name:Cache的唯一标识
maxElementsInMemory:内存中最大缓存对象数
eternal:Element是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久
有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大,单位是秒。
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和
失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间
无穷大,单位是秒。
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大。
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory
时,Ehcache将会Element钝化到磁盘中。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值