项目需要选择底层架构,Hibernate和Mybatis对比

本文对比分析了Hibernate和MyBatis两大ORM框架,深入探讨了它们在映射关系、底层配置、数据查询、对象管理等方面的差异,以及各自在业务场景、开发成本和调优方法上的优缺点。

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

Hibernate和Mybatis对比

Hibernate和Mybatis都是orm对象关系映射框架,都是用于将数据持久化的框架技术。

以下几点作为分析:

  1. 映射关系:

hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式。在hibernate4以后已经将annotationjar包集成进来了,如果使用hibernate3的版本就需要引入annotationjar包。

<!-- 基于annotation的配置 -->

        <mapping class="com.xiaoluo.bean.User"/>

<!-- 基于hbm.xml配置文件 -->

        <mapping resource="com/xiaoluo/bean/User.hbm.xml"/>

而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。

实现思路有两种:

1. 在使用 SQL 语句的时候,为每个字段定义别名; 
2. 使用 MyBatis 映射文件的 resultMap 标签。

  1. 底层配置:

针对初学者觉得hibernate的配置文件好麻烦,用hibernate还要写代码,还要写配置。Hibernate中配置主要分为两种:一种包含了Hibernate与数据库的基本连接信息,在Hibernate工作的初始阶段,这些信息被先后加载到Configuration和SessionFactory实例;另一种包含了Hibernate的基本映射信息,即系统中每一个类与其对应的数据库表之间的关联信息,在Hibernate工作的初始阶段,这些信息通过hibernate.cfg.xml的mapping节点被加载到Configuration和SessionFactory实例。这两种文件信息包含了Hibernate的所有运行期参数。以下是实现连接的基本方式:

第一种是使用hibernate.properties文件作为配置文件。

//实例化configuration对象 

Configuration cfg = new Configuration() 

//多次调用addResource()方法,添加映射文件 

cfg.addResource("Item.hbm.xml") 

cfg.addResource("Bid.hbm.xml"); 

查看hibernate.properties文件发现,该文件没有提供Hibernate映射文件的方式。因此使用hibernate.properties文件来作为配置文件时,必须使用Configuration.addResource()方法,使用该方法来添加映射文件

 

第二种是使用hibernate.cfg.xml文件作为配置文件。如下是样例

<hibernate-mapping> 

    <class name="com.bzu.hibernate.Student" table="student"> 

        <id name="id" column="id" type="string"> 

            <generator class="uuid"></generator> 

        </id> 

        <property name="name" column="name" type="string"></property> 

        <property  name="cardId"     column="cardId"type="string"></property> 

        <property name="age" column="age" type="int"></property> 

        <set name="courses" table="student_course" cascade="save-update"> 

            <key column="stu_id"></key> 

            <many-to-many class="com.bzu.hibernate.Course" column="course_id"> 

            </many-to-many> 

        </set> 

    </class> 

</hibernate-mapping></span> 

以上代码可以在配置hibernate开发环境时自动生成的。

mybatishibernate轻量了很多,少了很多配置

首先是读取mybatis的配置文件,创建工程类,获得session,调用SqlSession里面的方法进行数据库的相关操作。

factory = new SqlSessionFactoryBuilder().build(reader);

它的外层方法parseConfiguration(),进行具体的解析configuration下的子节点,并给configuration的对应变量赋值。

重点关注其中的:

environmentsElement(root.evalNode("environments")); //相当于jdbc配置数据源,以及事务的配置
mapperElement(root.evalNode("mappers"));//解析sql映射文件

  1. 数据查询:

在Hibernate里面Session的查询不能够胜任于复杂查询,所以现在的所有查询都通过Query接口完成,在这个接口里面要使用hql语言(及其类似于SQL语句)。比如:String hql="FROM News AS n";

Query query=HibernateSessionFactory.getSession().createQuery(hql);
在使用Hiberante进行数据查询的时候,发现所有的内容都会以POJO类的形式返回,所有的实例化操作部分都由Hibernate自动帮助用户处理了,

对于多表查询时编写HQL语言则会受到限制,营运在复杂场景的业务显得尤为笨重。

MyBatis进行数据库查询一定会用到SqlSessionFactory和SqlSession这两个类的对象,为了以后每次查询方便,就先构造有一个工具类,用来管理这两个对象:SqlSessionFactory的对象是重量级的,而SqlSession是轻量级的

另:mybatis在查询时可以传多个参数,批量删除,新增,修改,相比Hibernate更为灵活。可以根据业务场景多表联合查询,在报表导出比Hibernate尤为突出。

  1. 对象管理:

Hibernate 是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。也就是说,相对于常见的 JDBC/SQL 持久层方案中需要管理 SQL 语句,Hibernate采用了更自然的面向对象的视角来持久化 Java 应用中的数据。

 

换句话说,使用 Hibernate 的开发者应该总是关注对象的状态(state),不必考虑 SQL 语句的执行。这部分细节已经由 Hibernate 掌管妥当,只有开发者在进行系统性能调优的时候才需要进行了解。

而MyBatis在这一块没有文档说明,用户需要对对象自己进行详细的管理。

抓取策略

Hibernate对实体关联对象的抓取有着良好的机制。对于每一个关联关系都可以详细地设置是否延迟加载,并且提供关联抓取、查询抓取、子查询抓取、批量抓取四种模式。 它是详细配置和处理的。

而Mybatis的延迟加载是全局配置的。

 

  1. 对象关联机制:
Hibernate对实体关联对象的抓取有着良好的机制。对于关联关系都可以详细地设置是否延迟加载,并且提供关联抓取、查询抓取、子查询抓取、批量抓取四种模式,它是详细配置和处理的。
<!--关联配置 -->
<many-to-one name="grade" class = "entity.Grade" column="gid"></many-to-one>

 

Mybatis的延迟加载是全局配置的,也可以全局自定义配置:如ClazzMapper.xml

<mapper namespace="org.zang.mapper.ClazzMapper">

    <!-- 映射Clazz对象的resultMap -->

    <resultMap type="org.zang.domain.Clazz" id="clazzResultMap">

        <id property="id" column="id"/>

        <result property="code" column="code"/>

        <result property="name" column="name"/>

        <!-- 一对多关联映射:collection fetchType="lazy"表示懒加载  -->

        <collection property="students" javaType="ArrayList" column="id" ofType="org.zang.domain.Student"

        select="org.zang.mapper.StudentMapper.selectStudentByClazzId" fetchType="lazy">

          <id property="id" column="id"/>

          <result property="name" column="name"/>

          <result property="sex" column="sex"/>

          <result property="age" column="age"/>

      </collection>

    </resultMap>

    <!-- 根据id查询班级信息,返回resultMap -->

      <select id="selectClazzById" parameterType="int" resultMap="clazzResultMap">

          SELECT * FROM tb_clazz  WHERE id = #{id}

      </select>

</mapper>
  1. 缓存机制

hibernate的缓存机制,包括一级缓存(session级别)、二级缓存(sessionFactory级别)以及查询缓存其中持久化对象有三种状态,分别是:

transient(瞬时态):尚未与Session关联对象,失去引用的话,就会被JVM回收。一般就是直接New创建的对象。

persistent(持久态):已经与当前session产生关联,并且相关联的session没有关闭,并且事务尚未提交。

detached(脱管态):存在持久化OID,但没有与当前session关联,脱管状态改变hibernate不能检测到。

<span style="font-family:SimSun;font-size:18px;">// 获得Session 

            Session session = HibernateUtils.openSession(); 

            // 开启事务 

            Transaction transaction = session.beginTransaction(); 

            Book book = new Book(); // 瞬时态(没有OID,未与Session关联) 

            book.setName("hibernate精通"); 

            book.setPrice(56d); 

            session.save(book);// 持久态(具有OID,与Session关联) 

            // 提交事务,关闭Session 

            transaction.commit(); 

            session.close(); 

            System.out.println(book.getId()); // 脱管态(具有 OID,与Session断开关联) 

</span> 

   

hibernate向一级缓存放入数据时,同时保存快照数据,当修改一级缓存的时候,在flush操作时,对比缓存和快照,如果不一致,自动更新

 由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。

<!-- 开启二级缓存 -->
    <property name="hibernate.cache.use_second_level_cache">true</property>
    <!-- 为hibernate指定二级缓存的实现类 -->
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
hibernate的查询缓存是主要是针对普通属性结果集的缓存, 而对于实体对象的结果集只缓存id。

 

mybatis提供了缓存机制减轻数据库压力,提高数据库性能

mybatis的缓存分为两级:一级缓存、二级缓存

一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效

1.第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来

2.第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率

二级缓存是mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的;二级缓存默认是没有开启的。需要在setting全局参数中配置开启二级缓存,也可以针对某个表自定义开启,相比Hibernate更为灵活。
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>当前mapper下所有语句开启二级缓存
  1. 系统的调优解决方法:

Hibernate的调优方法可以采用:

1、制定合理的缓存策略;
2、尽量使用延迟加载特性;
3、采用合理的 Session 管理机制;
4、使用批量抓取,设定合理的批处理参数(batch_size)
5、进行合理的 O/R 映射设计

Mybatis的调优方法可以采用:

1、MyBatis 可以进行详细的 SQL 优化设计
2、MyBatis 在 Session 方面和 Hibernate 的 Session 生命周期是一致的, 同样需要合理的 Session 管理机制。 MyBatis 同样具有二级缓存机制。
8.SQL的优化

Hibernate的SQL调优方法可以采用:

1、使用的是封装好, 通用的 SQL 来应付所有场景;
2、查询时,会查询所有字段,会有不必要的性能消耗;

3、可以自己写SQL,但违背了框架的初衷。

Mybatis的SQL调优方法可以采用:

1、是针对响应的场景设计的 SQL,更灵活、 可控性更好、 更优化

2、SQL是手动编写的,按需查询

此处推荐mybatis做持久化操作.

  1. 可移植性

Hibernate: 1、与具体数据库的关联只需在 XML 文件中配置即可

2、所有的 HQL 语句与具体使用的数据库无关, 移植性很好

Mybatis: 1、所有的 SQL 语句都是依赖所用的数据库的

2、所以不同数据库类型的支持不好

  1. 动态SQL

Hibernate: 不支持

Mybatis:支持

  1. 业务场景

Hibernate: 针对业务场景复杂多变的情况,其灵活易开发优于Hibernate,实现业务要求的优化空间大

Mybatis: 复杂的业务场景开发效率低

  1. 开发成本

Hibernate: 托管spring,配置内容较少,容易上手,后期易于维护。

Mybatis: 全自动配置,底层配置复杂,多场景查询不灵活,开发时间成本较高。不熟悉Hibernate机制的开发人员开发难度加大

  1. 建议选择情况

Hibernate: 1、适用于中小企业需求变化不多的项目,对复杂多变的业务要求不高

2、其它条件满足,看团队大多数人员的倾向使用

3、对于不是熟悉Hibernate的开发者来说不易上手,后期开发吃力

   Mybatis: 1、数据量大(千万级),高并发

2、表关联复杂度(>20)

3、项目要求对于数据库可控性好, 可深度调优

4、后期易于维护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值