Hibernate ,Mybatis 区别,以及各自的一级,二级缓存理解

本文详细解析了Hibernate和Mybatis的一级、二级缓存机制,包括各自的优点和潜在问题。一级缓存默认开启,是线程独享的,而二级缓存默认关闭,可能引发数据一致性问题。在数据一致性要求较高的场景下,不建议过度依赖缓存,推荐使用外部缓存如Redis或Memcached。

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

区别:

1.Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,不过 mybatis 可以通过 XML 或注解方式灵活配置要运行的 sql 语句,并将java 对象和 sql 语句映射生成最终执行的 sql,最后将 sql 执行的结果再映射生成 java 对象,算是半自动ORM映射工具。
2.Mybatis 学习门槛低,简单易学,程序员直接编写原生态 sql,可严格控制 sql 执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是 mybatis 无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套 sql 映射文件,工作量大。
3.Hibernate 对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用 hibernate 开发可以节省很多代码,提高效率。因此他的数据库移植性很好,而Mybatis更换数据库,很多sql语句要大量修改。但是Hibernate 的缺点是学习门槛高,要精通门槛更高,而且怎么设计 O/R 映射,

原文链接:https://blog.youkuaiyun.com/banzhuanhu/article/details/110201816

一级缓存(内置缓存,都是默认开启)

1:一级缓存是默认开启的;
2:底层其实是基于hashmap的本地内存缓存;
3:作用域是session(其实就相当于在一个方法里,更准确说应该是一次与数据库的会话,一个方法如果提交了2次事务,就出现2个session了?);
4:当session关闭或者刷新的时候缓存清空;
5:不同sqlsession或者是hibernatesession之间缓存互不影响,是线程独享的;

导致的问题

数据一致性问题:
比如:我有一个更新操作对同一条数据,
如果是sqlsessionA进行了更新操作,则sqlsessionA对应的一级缓存被清空;(疑问?应该是sqlsessionA先进行查询操作,且一级缓存没清空 ,然后sqlsessionB更新操作后,导致的sqlsessionA再次查询数据不一致才对把???后面再测试)
如果是sqlsessionB进行了更新操作,则此更新操作对该sqlsessionA不可见;
那么其实这个时候sqlsessionA再查的数据就是过期失效数据了;
就出现了数据不一致现象;
建议
1:单个sqlsession的生命周期不能过长;
2:如果是对同一个语句更新尽量使用同一个sql,也就是同一个sqlsession;
3:建议关闭一级缓存,
 

Hibernate一级缓存是HibernateSession,session,,字面意思即会话。这里表示的是应用程序和数据库的一次交互(会话)。

所以,当一次交互过程中,涉及到对同对象查询时(比如一段代码里,有好几个地方都会查询某条姓名为“张三”的数据),除了第一次查询需要执行select的sql

语句去查询数据库,后面不用再去执行sql语句了,直接从缓存中拿数据。

代码验证:

  1. // 证明一级缓存的存在
  2. @Test
  3. public void test2() {
  4.     Session session = HibernateUtils.getSession(); // 得到session对象
  5.     session.beginTransaction();
  6.     // 获取goods1对象时,由于一级缓存中没有数据,所以会发送SQL语句,查询数据库中的内容
  7.     Goods goods1 = (Goods) session.get(Goods.class, 1);
  8.     System.out.println(goods1);
  9.     // 获取goods2对象时,不会发出SQL语句,会从Session缓存中获取数据
  10.     Goods goods2 = (Goods) session.get(Goods.class, 1);//根据id从缓存获取对象
  11.     System.out.println(goods2);
  12.     session.getTransaction().commit();
  13.     session.close();
  14. }

Session 缓存什么时候被清理?
1,commit() 方法被调用时。因为提交则表示,本次同数据库的会话已经完成,不会再用到。
2,查询时会清理缓存,保证查询结果能反映对象的最新状态。
3,显示的调用session 的 flush方法区清除缓存。
session 清理缓存的特例:
当对象使用 native 生成器 时 会立刻清理缓存向数据库中插入记录。

 

Mybatis 一级缓存 SqlSessio  同理

demo如下

@Test
    public void test1(){
        InputStream is = TestUser.class.getClassLoader().getResourceAsStream("application.xml");

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        SqlSession sqlSession = sqlSessionFactory.openSession();

        System.out.println("===========================================");
        User user1 = sqlSession.selectOne("getUserById",1001);
        System.out.println(user1);
        System.out.println("===========================================");
        User user2 = sqlSession.selectOne("getUserById",1001);
        System.out.println(user2);
        System.out.println("===========================================");
        sqlSession.close();
    }
 

 从打印的sql来看,在同一个SqlSession中,查询2次相同的数据时(实际上是通过mapper.xml找到的同一条sql语句),只会在第一次查询时,打印出一次sql,后面就从缓存直接拿了。这就是一级缓存的作用 。

可以通过mapper.xml中标签属性屏蔽一级缓存:flushCache="true" (默认是false,意为不清除缓存,也就是开启一级缓存的意思)具体如下:

å¨è¿éæå¥å¾çæè¿°

 

对比:Hibernate一级缓存,判断是否相同数据是根据缓存里 的对象id,如果是hibernate

通过hql语句或者sql语句去查询,则一级缓存没有起作用,还是每次都会执行查询。、

而Mybatis一级缓存,,是通过sql来判断是否为相同数据,也就是如果2次的sql语句一致,第二次就直接从缓存里拿。(当然前提也是在一次事务会话,事务提交后缓存也就清楚了,当然也可以手动清除缓存,和hibernate几乎一样的道理)

具体可以参考

https://blog.youkuaiyun.com/chengqiuming/article/details/100179998

 

二级缓存(外置缓存,都是默认关闭)

默认情况下默认也是采用 PerpetualCache,HashMap存储,SessionFactory 不会启用这个缓存插件,外置缓存中的数据是数据库数据的复制(可以缓存整个数据库?),外置缓存的物理介质可以是内存或硬盘。

二级缓存被多个SqlSession或HibernateSession共享,是一个全局的变量,线程共享,存在于SessionFactory的生命周期,是由SessionFactory管理的?

二级缓存坑的地方:

Mybatis:

你在OrderMapper.XML 和 UserMapp.XML的文件 都操作了User表的话,

当你使用OrderMapper.XML的SQL更新User表的时候,其他的SeqSession在OrderMapper.XML可以查到User表最新的数据,但是在UserMapp.XML查不到最新的数据

原因就是 二级缓存是基于某个XXXMapper.xml,每个Mapper直接独立,所以 不同Mapper操作同一张表的时候 (哪怕执行的是同一条sql,也要区分多个缓存对象?一级缓存也会吗??), 使用二级缓存会造成脏读

这也就是没什么人开启二级缓存的主要原因
原文链接:https://blog.youkuaiyun.com/weixin_35910783/article/details/113679318

 

当然二级缓存也不建议使用,mysql都默认关闭了,更何况我们呢。

缓存建议使用redis,mamcache等

 

 

参考:原文链接:https://blog.youkuaiyun.com/u010953880/article/details/104412646

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值