MyBatis 整理
撰写时间: 2020-01-16 总共: 7019 字 转载请注明: BY-SA 4.0(除特别声明或转载文章外)
MyBatis概述
MyBatis是主流的Java持久层框架,也是一种ORM框架。由于性能优异,高度灵活、可优化性、易于维护等特点被广泛使用。
原本是Apache的一个开源项目:iBatis,后来改名为MyBatis。提供包括SQL Maps和DAO(Data Access Objects),消除了JDBC代码和参数的手工设置以及结果集的检索。使用XML或者注解的方式进行POJO的数据库映射。不同与Hibernate全映射框架,MyBatis是一个半自动的映射,需要手动匹配POJO、SQL和映射关系。
- MyBatis环境构建
- MyBatis的工作原理
- 与Spring进行整合
MyBatis环境
项目引入MyBatis jar包即可。
配置文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 配置 -->
<properties /><!-- 属性 -->
<settings /><!-- 设置 -->
<typeAliases /><!-- 类型命名 -->
<typeHandlers /><!-- 类型处理器 -->
<objectFactory /><!-- 对象工厂 -->
<plugins /><!-- 插件 -->
<environments><!-- 配置环境 -->
<environment><!-- 环境变量 -->
<transactionManager /><!-- 事务管理器 -->
<dataSource /><!-- 数据源 -->
</environment>
</environments>
<databaseIdProvider /><!-- 数据库厂商标识 -->
<mappers /><!-- 映射器 -->
</configuration>
MyBatis 配置项的顺序不能颠倒。如果颠倒了它们的顺序,那么在 MyBatis 启动阶段就会发生异常,导致程序无法运行。
MyBatis的工作原理
与Spring整合
引入相关的依赖,将MyBatis的SqlSessionFactory交由Spring进行构建。
<!--配置数据源-->
...
<!--配置MyBatis工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--MyBatis核心配置文件-->
<property name="configLocation" value="classpath:com/mybatis/mybatis-config.xml"/>
</bean>
<!--基于MapperScannerConfigurer的数据操作接口整合-->
<!--将@Mapper注解自动装配为MyBatis的映射接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
-
创建PO
-
创建DAO
@Mapper 注解的DAO接口
-
创建Mapper 对应的PO的XML
DaoMapper.XML
MyBatis映射器
MyBatis的强大之处体现在SQL映射文件上,映射器是MyBatis最复杂且最重要的组件,由一个接口加上SQL映射文件组成。除了XML外也有注解。
SQL映射文件(.xml)主要使用的配置元素:
- select
- insert
- update
- delete
- sql
- resultMap
主要是查询、插入、更新、删除、数据库返回结构处理。
select
.示例:
比如存在一个UserMapper.xml
,存在DAO接口方法:selectAllUser
<select id="selectAllUser" resultType="com.po.User" parameterType="map或者一个普通JavaBean">
select * from user
where uname like concat('%',#{u_name},'%')
and usex=#{u_sex}
</select>
选择map或者JavaBean来传递查询参数看情况而定。
insert
用于插入数据库返回一个整数,表示影响的行数。属性基本与查询相同,特有属性:
-
keyProperty
将插入或更新的返回值,赋予某个PO类的某个属性。常设置主键对应的属性。
-
keyColumn
用来设置第几列是主键,表里第一列不是主键时需要设置。
-
useGeneratedkeys
设置该属性为true时,将使用JDBC的
getGeneratedKeys()
获取数据库内部产生的主键,默认为false。
业务上需要在插入成功时,返回当前插入对象的主键,这时候我们就需要进行主键回填
自动递增的情况下:
如mysql:
将会回填到添加进入的user的主键uid
<insert id="addUser" parameterType="com.po.User" keyProperty="uid" useGeneratedKeys="true">
insert into user(uname,usex) values(#{uname},#{usex})
</insert>
在主键不自动递增的情况下:
可以使用MyBatis的<selectKey>
来指定生成主键。
<insert id="addUser" parameterType="com.po.User">
<selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
select if(max(uid) is null , 1 , max(uid)+1) as newUid from user
</selectKey>
insert into user(uid,uname,usex) values(#{uid},#{uname},#{usex})
</insert>
其中keyProperty
指定了返回PO类的属性为uid,order
指定可以选择 BEFORE
或者AFTER
,分别指定在插入数据前执行还是插入后执行。
update
<update id="updateUser" parameterType="com.po.User">
update user set uname=#{uname},usex=#{usex} where uid=#{uid}
</update>
delete
<delete id="deleteUser" parameterType="com.po.User">
delete from user where uid=#{uid}
</delete>
将上述的CRUD等元素在对应的Mapper.xml
中进行对应方法接口的SQL映射是关键。
sql
<sql>
主要是用来定义一个SQL语句的一部分,方便重用。
如:
<sql id="selectColumns">uid,uname,usex</sql>
<select id="selectAllUser" resultType="com.po.User">
select <include refid="selectColumns"/> from user
</select>
使用<include refid="引用的sql语句">
进行嵌入。
resultMap
该元素表示结果映射集,主要用以定义映射规则、级联的更新以及定义类型转化器等。
主要体现在自定义返回结果映射结构。
一个resultMap的定义
<resultMap type="需要的POJO类" id="该结果集结构的唯一标识">
<constructor> <!--类在实例化时用以注入结果到构造方法,POJO未定义无参数构造方法时使用-->
<idArg/> <!--ID参数,对应ID-->
<arg/> <!--普通结果-->
</constructor>
<id property="POJO对应主键属性" column="查询结果的列名"/> <!--表示哪一列是主键-->
<result property="POJO对应属性" column="查询结果的列名"/> <!--表示POJO和数据表普通列的映射关系-->
<association property=""/> <!--用以一对一关联-->
<collection property=""/> <!--一对多,多对多关联-->
<discriminator javaType=""> <!--使用结果值来决定那些结果进行映射-->
<cass value=""/> <!--基于某些值的结果映射-->
</discriminator>
</resultMap>
对于查询的结果映射可以使用Map,也可以使用POJO,大多数使用POJO,可以进行自动映射。
当存在级联查询的时候,需要进行一个resultMap的定义使用。
示例一个使用POJO进行返回。
省略POJO类,等,关注于xml的编写
<!--
User{
m_id;
m_name;
m_sex;
}
public List<User> allUser();
-->
<resultMap type="com.po.User" id="userResult">
<id property="m_id" column="uid"/>
<result property="m_name" column="uname"/>
<result property="m_sex" column="usex"/>
...
</resultMap>
<select id="allUser" resultMap="userResult">
select * from user
</select>
级联查询
- 一对一
- 一对多
- 多对多
3种级联关系,级联可以在获取数据的时候提供方便,但是级联过多会增加数据库系统的复杂度,降低系统性能。
更新和删除的级联关系,依靠数据库的内在机制即可完成,而查询的级联关系,我们需要进行级联查询处理。
对于一对一采取多种方式进行SQL查询,比如连接查询,嵌套查询(执行2次SQL)等。主要是进行resultMap的association指定。
对于一对多,与多对多,collection的设置为关键。(多对多转化中间表变一对多)
但是级联查询结果均可以使用POJO来进行自动的映射。
动态SQL
MyBatis的动态SQL元素与JSTL相似,常用:
<if></if>
<choose></choose>
<when></when>
<otherwise></otherwise>
<trim></trim>
<where></where>
<set></set>
<foreach></foreach>
<bind></bind>
<select id="queryUser" resultType="com.po.User" parameterType="com.po.User">
select * from user where 1=1
<!--if示例-->
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
...
<!--choose示例-->
<choose>
<when test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</when>
<otherwise>
and uid > 10
</otherwise>
</choose>
...
<!--trim示例
prefix,suffix:可以在对应的内容前加上某些前缀和后缀。
prefixOverrides,suffixOverrides:忽略某些前缀或后缀
-->
<!--构造一个where子句-->
<trim prefix="where" prefixOverrides="and|or">
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
</trim>
...
<!--where示例
where将生成一个where子句,自动忽略and开头或者or开头
where内部MyBatis将自动补上空格,所有条件都不满足时会将所有记录都查询出来
-->
<where>
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
</where>
</select>
<!--set 将在update中动态地更新-->
<update id="updateUser" parameterType="com.po.User">
update user
<set>
<if test="uname!=null and uname!=''">
uname=#{uname}
</if>
</set>
where uid = #{uid}
</update>
<!--foreach
item, 集合中的一个元素
index, 迭代到的下标
collection, 集合是必选的,可以是List,array,Map
open, 表示该语句以啥符号开始
separator, 表示该语句以啥符号进行分隔
close, 表示以啥符号结束
-->
<select id="queryUserByIdList" resultType="com.po.User" parameterType="List">
select * from user where uid in
<!-- (1,2,3,4,5..) -->
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<!--bind-->
<select id="queryUser" resultType="com.po.User" parameterType="com.po.User">
<!-- 使用bind进行模糊查询,解决不同数据库中模糊查询连接字符不一样的问题 -->
<bind name="like_param" value="'%'+uname+'%'"/>
select * from user where uname like #{like_param}
</select>