前言:
MyBatis是一个支持普通SQL查询、存储过程和高级映射的持久层映射框架,其设计思想重心在于将大量的SQL从代码中分离出来,以实现SQL的灵活配置。相对于与Hibernate等全自动的ORM框架而言,其是半自动的ORM框架,准确来说,是一个SQL Mapping框架,着力点在于POJO与SQL之间的映射,对于具体的数据操作,则需要程序员自行编写SQL,可对SQL进行优化,提高查询效率,是对全自动ORM机制的一种有益补充。本篇博文主要讲解springBoot如何与MyBatis整合。
正文:
一。在pom.xml文件中引入相关依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
二。在application.yml文件中配置数据源
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml
type-aliases-package: com.dmsdbj.integral.kernel.entity
mapper-locations: classpath:mybatis/mapper/**/*.xml
在yml文件中提到三类文件:
1.config-location:配置文件:mybatis.cfg.xml
<?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>
<settings>
<setting name="cacheEnabled" value="true"/><!-- 二级缓存开启 -->
<!--启用mybatis mapUnderscoreToCamelCase 特性,可以更方便智能完成自定义对象的装配。
eg:column name = audit_state,可以自动mapping/set自定义对象的属性auditState。-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
主要作用是开启了MyBatis的二级缓存。MyBatis的缓存分为一级缓存和二级缓存,一级缓存是SqlSession级别的缓存,默认是开启的,无需任何配置,其作用域是在同一个SqlSession中,存储介质为内存;二级缓存是Mapper级别的缓存,默认没有开启,需要在全局setting参数中配置,如上代码所示,其作用域是同一个mapper下的同一个namespace,跨sqlsession的,比一级缓存的范围大,开启二级缓存接口必须实现java.io.Serializable,进行序列化和反序列化操作,因为二级缓存的存储介质是多种多样的,在其映射文件中配置<cache/>.MyBatis的缓存是以HashMap的形式存储的,以对象的id作为key,以对象作为value。
2.type-aliases-package:类型别名包
/**
*
* action
*/
@ApiModelProperty(value = "action",required = false)
@Column(name = "action")
private String action;
对象属性与数据表映射。
3.mapper-locatioins:映射文件位置
包含两种文件,一种是允许程序员编写SQL的xml文件,一种是POJO与数据库表的映射
(1)mapper-base.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.dmsdbj.integral.library.provider.dao.ActionDao">
<resultMap id="BaseResultMap" type="com.dmsdbj.integral.library.entity.ActionEntity">
<result column="id" property="id" jdbcType="VARCHAR" />
<result column="action" property="action" jdbcType="VARCHAR" />
<result column="is_calculation" property="isCalculation" jdbcType="TINYINT" />
<result column="operator" property="operator" jdbcType="VARCHAR" />
<result column="creator" property="creator" jdbcType="VARCHAR" />
<result column="user_id" property="userId" jdbcType="VARCHAR" />
<result column="is_top_lottery" property="isTopLottery" jdbcType="TINYINT" />
<result column="is_improve_lottery" property="isImproveLottery" jdbcType="TINYINT" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="is_delete" property="isDelete" jdbcType="TINYINT" />
</resultMap>
<sql id="Base_Column_List">
id,
action,
is_calculation,
operator,
creator,
user_id,
is_top_lottery,
is_improve_lottery,
remark,
create_time,
update_time,
is_delete
</sql>
</mapper>
namespace是DAO层的类全路径名,resultMap是结果集的映射,标签内部编写的是对象属性与数据表列的一一映射,有了映射机制之后,MyBatis会通过反射创建对象,同时通过反射给该对象一一复制,部分没有映射成功的属性,便不能给其赋值。
(2)mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.dmsdbj.integral.library.provider.dao.ActionDao">
<select id="queryActionList" resultType="com.dmsdbj.integral.library.entity.ActionEntity">
SELECT
r.id,
r.user_id,
u.user_name,
r.action,
r.create_time
FROM
tli_action r
LEFT JOIN tc_allusers u ON r.user_id = u.id
WHERE
r.is_calculation = 0
AND r.is_delete = 0
AND (r.create_time between #{startDate} and #{endDate})
</select>
</mapper>
namespace是DAO接口类的全路径名,select标签的id,是DAO层接口类的方法名。xml映射文件与DAO接口的对应是通过DAO寻找xml对应的sql的时候是权限名+方法名的保存 和寻找策略的。DAO的工作原理为jdk动态代理,运行时会为DAO生成一个proxy,代理对象会拦截接口方法,然后执行对应的sql返回数据。
三。DAO层添加注解-@mapper
(1)引入mapper: import org.apache.ibatis.annotations.Mapper;
(2)在DAO层接口上面添加@mapper注解
mapper接口开发方法只需要程序编写mapper接口(相当于DAO接口),由MyBatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体与DAO接口实现类方法一致。
使用MyBatis的mapper接口开发有以下规范需要遵守:
(1)mapper接口方法名与mapper.xml文件中定义的每个sql的id相同
(2)mapper接口全路径名与mapper.xml文件中的namespace一致
(3)mapper接口方法的输入参数与mapper.xml文件中定义的每个sql的parameterType一致
(4)mapper接口方法的输出参数与mapper.xml文件中定义的每个sql的resultType一致
备注:
通常在DAO层还会使用@Repository("actionDao"),引入import org.springframework.stereotype.Repository;来使用,这个注解是告诉spring,让spring创建一个名字叫“actionDao”的UserDaoImpl实例,当service需要使用spring创建的名字叫“actionDao”的UserDaoImpl实例时,就可以使用@Resource(name=“actionDao”)注解告诉spirng,spring把创建好的actionDao注入给service即可。
四。在mapper.xml中编写sql
<select id="queryActionList" resultType="com.dmsdbj.integral.library.entity.ActionEntity">
SELECT
r.id,
r.user_id,
u.user_name,
r.action,
r.create_time
FROM
tli_action r
LEFT JOIN tc_allusers u ON r.user_id = u.id
WHERE
r.is_calculation = 0
AND r.is_delete = 0
AND (r.create_time between #{startDate} and #{endDate})
</select>
此sql语句传递了两个参数,在mapper中传递多个参数有另种方式:
(1)直接在方法中传递多个参数,mapper.xml文件中使用#{0},#{1}来接收
(2)使用@param注解来传递多个参数,mapper.xml文件中使用#{name}来接收
#{}是预处理语句,mybatis在处理#{}时,将其转换为?,调用parperStatedment的set方法来进行赋值,其也可以防止SQL注入增加安全性。${}是字符串替换,mybatis在处理${}时,将其替换为字符串变量的值。
MyBatis还有一个强大的特性是动态sql,其可以让程序员在xml映射文件中,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。具体包括的元素包括:if/where/when/choose/otherwise/foreach/set/bind,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
MyBatis一般通过if节点来设定,通过OGNL的语法来实现。如果要实现得完整,必须配合where和trim节点,where通过包含有节点内容就插入where,否则就不插入。trim如果sql语句中有以and或者or为开头,自动将and或者or去掉。
结语:
使用mybatis可以让大量的sql从代码中抽离出来,通过简单的配置便可以应用,后期的维护大大便利。其底层封装了JDBC API的具体实现,大大简化了java数据库重复编程的工作量。mybatis的着力点在于POJO和sql之间的映射,具体的数据操作,让程序员自行编写,这样就可以有更加灵活地选择和配置。