jpa的脏数据更新

脏数据更新的原理

文字描述脏数据更新的原理:
当我们使用entityManager去查询数据之后,JPA会自动在内存中生成一份快照数据(相当于是查询出
来的持久状态对象的一个备份),然后当我们调用对象的属性set方法后,修改了持久状态对象的属性
值,当事务提交的时候,JPA会自动去比对那个持久状态对象和那个快照对象,如果发现数据不一致
了,就称那个持久状态对象为脏数据;由于这个对象是持久状态的,而JPA规定持久状态数据必须与数
据库表中的数据完全保持一致,为了达到这个目的,所以在事务提交时会自动发出update语句去修改数
据,这就是脏数据更新,所以即使不要merge方法也能够修改数据。
/**
* 测试脏数据更新
* 测试:使用entityManager查询一个对象出来,然后设置对象的属性值,然后提交事务,我们发现
即使吧
* merge方法这一行代码去掉,JPA也能去修改数据,太神奇了!!!这个现象就称为脏数据更新
* 原因:
*
* @throws Exception
*/
@Test
public void testUpdate() throws Exception{
//传入一个persistence-unit标签的name属性,创建一个工厂对象
EntityManagerFactory factory =
Persistence.createEntityManagerFactory("jpa_day02");
//通过工厂对象创建一个EntityManager对象,这是JPA的核心对象,JPA的所有操作都要依赖于EntityManager对象
EntityManager entityManager = factory.createEntityManager();
//查询一个对象出来:持久状态
Employee employee = entityManager.find(Employee.class, 1L);
employee.setName("张翠山");
//开启事务
entityManager.getTransaction().begin();
//修改数据
//entityManager.merge(employee);
//提交事务
entityManager.getTransaction().commit();
//关闭资源
entityManager.close();
factory.close();
}

通过不用merge方法也可以修改数据

二级缓存

导入jar包
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.8.Final</version>
</dependency>

开启二级缓存配置导入
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache" value="true" />
<!-- 二级缓存的实现类 -->
<!-- 错误 org.hibernate.cache.internal.EhCacheRegionFactory -->
<!-- 正确的 org.hibernate.cache.ehcache.EhCacheRegionFactory -->
<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>

二级缓存的使用场景

读取大于修改;--- 查询次数远远高于增删改
对数据要有独享控制,数据不会被第三方修改;如果有多个项目同时连接同一个数据库,不适合使用二级缓存
可以容忍出现无效数据,非关键数据(不是财务数据等)
数据量不能超过内存容量,数据量特别巨大,此时不适合于二级缓存(*钝化*)
钝化:将对象数据从内存中写入到硬盘文件中,采用了Java的 ObjectOutputStream 来传输,要求实	体类必须实现Serializable接口

懒加载原理

① 当我们调用 employee.getDepartment() 的时候,JPA底层会使用javassist这个字节码工具包自动
生成一个类,名称为Department$$jvst5b8_1.java
② Department$$jvst5b8_1.java 类继承了 Department 类,并且重写了类中的所有属性的get方
法,在重写方法中调用了entityManager对象的find方法去查询部门数据
③ 由于这是一个java源文件,无法运行,所以就采用 Java动态编译技术 将其编译成class文件
④ 利用类加载器 ClassLoader 将class文件加载到java虚拟机中,得到一个Class字节码对象
⑤ 利用反射技术创建该类的对象, Class对象.newInstance() 最后返回这个对象
也就是说,employee.getDepartment() 方法得到的对象其实是Department的子类对象,等价于:
而这个子类中又重写了父类的属性的get方法,所以当你调用 department.getName() 的时候,会出现
多态的效果(执行子类重写后的方法,忽略父类被重写的方法),JPA会去查询数据。
发布了17 篇原创文章 · 获赞 1 · 访问量 182

猜你喜欢

转载自blog.csdn.net/weixin_43404554/article/details/105579438
今日推荐