Hibernate和MyBatis
这两个框架的主要区别如下:
Hibernate简介
是一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。
开发者并不需要熟练的掌握SQL语句的编写,Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。
然而Hibernate自身也存在着一些缺点:例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
MyBatis简介
是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。
与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。
MyBatis框架是当前主流的Java持久层(数据访问层DAO)框架之一,它与Hibernate一样,也是一种ORM(Object/Relation Mapping,即对象关系映射)框架。
Mybatis是一个数据持久层(ORM)框架,把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现。
所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。
MyBatis核心组件
SqlSessionFactoryBuilder(构造器)
根据XML配置(推荐方式)或者代码来生成SqlSessionFactory(工厂接口)对象, 创建完成后该对象就不需要了,所以只需要使用一次,后面无需保存。
SqlSessionFactory
依靠工厂来创建SqlSession(会话)对象;该对象是线程安全的,所以整个应用只需要保存一个。
SqlSession
类似于一个JDBC的Connection对象。是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口。
SQL Mapper
是MyBatis新设计的组件,是由一个Java接口和XML文件(或注解)构成的,需要给出对应的SQL和映射规则。负责发送SQL去执行,并返回结果。通过namespace.id调用Mapper中定义的SQL。
MyBatis框架的工作执行流程如下
(1)读取MyBatis配置文件mybatis-config.xml
(2)加载映射文件Mapper.xml
(3)构建会话工厂
(4)创建SqlSession对象
(5)使用Executor接口来操作数据库
(6)使用MappedStatement类型的参数对映射信息进行封装。
(7)输入参数映射
(8)输出结果映射
<sql>元素的作用就是定义可重用的SQL代码片段。
使用时,先通过<sql>元素定义重用的代码片段,然后在需要使用的地方使用<include>元素的refid属性引用了自定义的代码片段。
MyBatis核心对象SqlSessionFactory的获取方式
SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来构建,而SqlSessionFactoryBuilder则可以通过XML配置文件或一个预先定义好的Configuration实例构建出SqlSessionFactory的实例,通过XML配置文件构建出的SqlSessionFactory实例,
代码实现
// 读取配置文件 InputStream inputStream = Resources.getResourceAsStream("配置文件位置"); // 根据配置文件构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
MyBatis使用过程
- 使用SqlSessionFactoryBuilder创建SqlSessionFactory对象;
- 然后通过SqlSessionFactory创建SqlSession对象;
- 通过SqlSession对象完成基本操作(执行SQL)。
- 关闭SqlSession。
mapper元素子元素及其作用
在映射文件中,<mapper>元素是映射文件的根元素,其他元素都是它的子元素。这些子元素及其作用如下所示:
<select>:用于映射查询语句,可自定义参数,返回结果集等。
<insert>:用于映射插入语句,执行后返回一个整数,代表插入的条数。
<update>:用于映射更新语句,执行后返回一个整数,代表更新的条数。
<delete>:用于映射删除语句,执行后返回一个整数,代表删除的条数。
<sql>:用于定义一部分SQL,然后可被其他语句引用此SQL。
<cache>:用于给定命名空间的缓存配置。
<cache-ref>:用于其他命名空间缓存配置的引用。
<resultMap>:用于描述如何从数据库结果集中来加载对象。
resultMap元素
当数据表中的列和需要返回的对象的属性不完全一致, MyBatis是不会自动赋值的。此时,就可以使用<resultMap>元素进行处理。
<resultMap>元素的子元素<id>用于表示哪个列是主键,而<result>元素用于表示POJO和数据表中普通列的映射关系。
<resultMap id="custResultMap" type="Customer"> <id property="id" column="id" /> <result property="custId" column="cust_id"/> <result property="name" column="name"/> </resultMap>
include元素的refid属性
MyBaits映射文件中使用<include>元素的refid属性可以引用自定义的代码片段,其属性值为自定义代码片段的id
<sql id="custColumns"> cust_id custId,name,age </sql> <select id="sqlCustList" resultType="Customer"> select <include refid="custColumns" /> from customer c </select>
include元素的refid属性
MyBaits映射文件中使用<include>元素的refid属性可以引用自定义的代码片段,其属性值为自定义代码片段的id
<sql id="custColumns"> cust_id custId,name,age </sql> <select id="sqlCustList" resultType="Customer"> select <include refid="custColumns" /> from customer c </select>
namespace属性
MyBatis映射文件中<mapper>元素是配置文件的根元素,它包含一个namespace属性,该属性为这个<mapper>指定了唯一的命名空间。在Mybatis映射文件中,每个操作都有一个id属性表示操作的唯一标识
<mapper namespace="customer"> <select id="customerList" resultType="Customer"> select * from customer </select> </mapper>
insert元素
MyBatis映射文件中<insert>元素用于映射插入语句,在执行完元素中定义的SQL语句后,与<update>和<delete>元素在执行完之后一样,也会返回一个表示影响记录条数的整数。
<insert>元素的属性与<select>元素的属性不同,可以使用keyProperty属性指定哪个是主键字段,使用useGeneratedKeys属性定义主键是否使用数据库内置策略生成,从而实现对于表中自增编号主键列的主键回填和自定义功能。
根据MyBatis的映射文件编写Mapper接口过程中涉及的关键问题如下
通常一个映射文件对应一个Mapper接口,映射文件中的namespace与接口的全限定名一致。
映射文件中每个操作id对应Mapper接口的一个方法,方法名与映射文件中操作的id相同,参数类型和返回值类型与操作中的parameterType和resultType相同
SQL调用的时候通过接口调用,而不用再指出操作的id
MyBatis配置XML文件结构
mybatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息。
<configuration><!--配置--> <properties/><!--属性--> <settings/><!--设置--> <typeAliases/><!--类型命名--> <typeHandlers/> <!--类型处理器--> <objectFactory/> <!--对象工厂--> <plugings/> <!--插件--> <environments> <!--配置环境--> <environment> <!--环境变量--> <transactionManager/><!--事务管理器--> <dataSource/> <!--数据源--> </environment> </environments> <databaseIdProvider/><!--数据库厂商标识--> <mappers/> <!--映射器--> </configuration>
这些层次是不能够颠倒顺序的,如果颠倒顺序,MyBatis在解析XML文件的时候就会出现异常。
例如:
<configuration> <typeAliases> <typeAlias type="entity.Customer" alias="Customer" /> <typeAlias type="entity.Course" alias="Course" /> <typeAlias type="entity.QuickManual" alias="QuickManual" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <!-- ?useUnicode=true&characterEncoding=utf8为了支持中文数据的写入 --> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/CustomerMapper.xml" /> <mapper resource="mapper/CourseMapper.xml" /> <mapper resource="mapper/QuickManualMapper.xml" /> </mappers> </configuration>