MyBatis
是一个基于 Java
的持久层框架,它内部封装了 JDBC
,使开发者只需关注 SQL
语句自己,而不用再花费精力去处理诸如注册驱动、建立 Connection
、配置 Statement
等繁杂过程。java
Mybatis
经过 xml
或注解的方式将要执行的各类 Statement
、PreparedStatement
等配置起来,并经过 Java
对象和 Statement
中 SQL
的动态参数进行映射生成最终执行的 SQL
语句,最后由 MyBatis
框架执行 SQL
并将结果映射成 Java
对象并返回。程序员
Hibernate 框架是提供了全面的数据库封装机制的 全自动 ORM,即实现了 POJO 和数据库表之间的映射,以及 SQL 的自动生成和执行。spring
相对于此,MyBatis 只能算做是 半自动 ORM。其着力点,是在 POJO 类与 SQL 语句之间的映射关系。也就是说,MyBatis 并不会为程序员自动生成 SQL 语句。具体的 SQL 须要程序员本身编写,而后经过 SQL 语句映射文件,将 SQL 所需的参数,以及返回的结果字段映射到指定 POJO。sql
XML
文件中配置 SQL
语句,实现了 SQL
语句与代码的分离,给程序的维护带来了很大便利。SQL
语句,所以可以实现比 Hibernate
等全自动 ORM
框架更高的查询效率,可以完成复杂查询。在 pom.xml
引入 Mybatis 相关依赖。数据库
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.17.RELEASE</version> </dependency>
在 resource
目录下建立 mybatis-config
配置文件。数组
<?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> <!-- 打印 SQL 语句 --> <setting name="logImpl" value="STDOUT_LOGGING" /> <!-- 使全局的映射器启用或禁用缓存。 --> <setting name="cacheEnabled" value="false"/> <!-- 全局启用或禁用延迟加载。当禁用时,全部关联对象都会即时加载。 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 当启用时,有延迟加载属性的对象在被调用时将会彻底加载任意属性。不然,每种属性将会按须要加载。 --> <setting name="aggressiveLazyLoading" value="true"/> <!-- 是否容许单条 SQL 返回多个数据集 (取决于驱动的兼容性) default:true --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 是否能够使用列的别名 (取决于驱动的兼容性) default:true --> <setting name="useColumnLabel" value="true"/> <!-- 容许 JDBC 生成主键。须要驱动器支持。若是设为了 true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然能够执行。 default:false --> <setting name="useGeneratedKeys" value="false"/> <!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE:不映射 PARTIAL:部分 FULL:所有 --> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器能够重复执行语句和批量更新) --> <setting name="defaultExecutorType" value="SIMPLE"/> <!-- 使用驼峰命名法转换字段。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session --> <setting name="localCacheScope" value="SESSION"/> <!-- 设置 JDBC 类型为空时,某些驱动程序 要指定值, default:OTHER,插入空值时不须要指定类型 --> <setting name="jdbcTypeForNull" value="NULL"/> </settings> </configuration>
在 resource
目录下建立一个 spring-context-mybatis.xml
的集成配置文件。缓存
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置 SqlSession --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 用于配置对应实体类所在的包,多个 package 之间能够用 ',' 号分割 --> <property name="typeAliasesPackage" value="com.antoniopeng.ssm.domain"/> <!-- 用于配置对象关系映射--> <property name="mapperLocations" value="classpath:/mapper/**/*.xml"/> <!-- -用于配置文件所在目录-> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> </bean> <!-- 扫描 Mapper --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.antoniopeng.ssm.dao" /> </bean> </beans>
<insert id="insert"> INSERT INTO tb_user ( id, username, password, phone, email, created, updated ) VALUES ( #{id}, #{username}, #{password}, #{phone}, #{email}, #{created}, #{update} ) </insert>
<delete id="delete"> DELETE FROM tb_user WHERE id = #{id} </delete>
<select id="getById" resultType="TbUser"> SELECT a.id, a.username, a.password, a.phone, a.email, a.created, a.updated AS "update" FROM tb_user AS a WHERE a.id = #{id} </select>
<update id="update"> UPDATE tb_user SET username = #{username}, password = #{password}, phone = #{phone}, email = #{email}, created = #{created}, updated = #{update} WHERE id = #{id} </update>
动态 SQL 主要用于解决查询条件不肯定的状况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不一样,执行的 SQL 语句不一样。若将每种可能的状况均逐一列出,对全部条件进行排列组合,将会出现大量的 SQL 语句。此时,可以使用动态 SQL 来解决这样的问题。这里的条件判断使用的表达式为 OGNL
表达式。经常使用的动态 SQL 标签有 <if>
、<where>
、<choose>
、<foreach>
等。session
注意:在 mapper 的动态 SQL 中若出现 >
、<
、>=
,<=
等符号,最好将其转换为实体符号。不然,XML 可能会出现解析出错问题,特别是 <
在 XML 中是绝对不能出现的。mybatis
对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段拼接到其所在的 SQL 语句中。
案例
为了解决两个条件均未作设定的状况,在 where 后添加了一个“1=1”的条件。这样就不至于两个条件均未设定而出现只剩下一个 where,而没有任何可拼接的条件的不完整 SQL 语句。app
<?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.antoniopeng.ssm.dao.StudentDao"> <!-- if --> <select id="selectByIf" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student WHERE 1 = 1 <if test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </if> <if test="age != null and age > 0"> AND age > #{age} </if> </select> </mapper>
案例
<select id="selectByWhere" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <where> <if test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </if> <if test="age != null and age > 0"> AND age > #{age} </if> </where> </select>
该标签中只能够包含 <when/>
、<otherwise/>
,能够包含多个 <when/>
与一个 <otherwise/>
。它们联合使用,完成 Java 中的开关语句 switch case 功能。
案例
本例要完成的需求是,若姓名不空,则按照姓名查询;若姓名为空,则按照年龄查询;若没有查询条件,则没有查询结果。
<!-- choose --> <select id="selectByChoose" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <where> <choose> <when test="name != null and name != ''"> AND name LIKE concat('%', #{name}, '%') </when> <when test="age != null and age > 0"> AND age > #{age} </when> <otherwise> AND 1 != 1 </otherwise> </choose> </where> </select>
该标签用于实现对于数组与集合的遍历。对其使用,须要注意:collection
表示要遍历的集合类型,这里是数组,即 array。open
、close
、separator
为对遍历内容的 SQL 拼接。
遍历数组案例
<!-- foreach --> <select id="selectByForeach" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="array != null and array.length > 0"> WHERE id IN <foreach collection="array" open="(" close=")" item="id" separator=","> #{id} </foreach> </if> </select>
遍历泛型为基本类型的集合案例
/** * 使用 foreach 标签以 list 基本类型的形式查询 * @param ids * @return */ public List<Student> selectByForeachWithListBase(List<Long> ids);
<!-- foreach --> <select id="selectByForeachWithListBase" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="list != null and list.size > 0"> WHERE id IN <foreach collection="list" open="(" close=")" item="id" separator=","> #{id} </foreach> </if> </select>
遍历泛型为自定义类型的集合案例
/** * 使用 foreach 标签以 list 自定义类型的形式查询 * @param students * @return */ public List<Student> selectByForeachWithListCustom(List<Student> students);
<!-- foreach --> <select id="selectByForeachWithListCustom" resultType="com.antoniopeng.ssm.entity.Student"> SELECT * FROM student <if test="list != null and list.size > 0"> WHERE id IN <foreach collection="list" open="(" close=")" item="student" separator=","> #{student.id} </foreach> </if> </select>
该标签用于定义 SQL 片段,以便其它 SQL 标签复用。而其它标签使用该 SQL 片段, 须要使用 <include/>
子标签。该标签能够定义 SQL 语句中的任何部分,因此 <include/>
子标签能够放在动态 SQL 的任何位置。
案例
<sql id="select"> SELECT id, name, age, score FROM student </sql>
使用 sql 标签
<!-- foreach --> <select id="selectByForeachWithListCustom" resultType="com.antoniopeng.ssm.entity.Student"> <include refid="select" /> </select>