7.MyBatis 核心配置以及动态SQL
7.1 MyBatis的核心对象
7.1.1SqlSessionFactory
它是一个十分重要的对象,是单个数据库映射关系经过编译后的内存镜像,主要作用是用来创建Session,SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用执行期间都会存在,如果我们多次创建同一个数据库的SqlSessionFactory,那么此数据库的资源很容易被耗尽。因此,通常每一个数据库都会只对应一个SqlSessionFactory。
7.1.2SqlSession
它是应用程序与持久层之间执行交互操作的一个单线程对象,其主要作用是执行持久化操作,SqlSession包括了所有的执行SQL操作的方法,它是线程不安全的,因此其使用范围最好在一次请求或一个方法中,
利用工具类创建SqlSession
package com.itheima.utils;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
static {
try {
Reader reader =
Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory =
new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSession getSession() {
return sqlSessionFactory.openSession();
}
}
7.1.3< sql > 元素
这个并非核心对象,这是一个配置元素标签,这个元素相当于声明了一个变量
定义格式如下
<sql id="customerColumns">id,username,jobs,phone</sql>
这个就像我们定义String name = "hellloworld" 赋予name了值
这里我们通过sql便签赋予customerColumns值id,username,jobs,phone
这样我们可以写出以下语句
<select id="findCustomerById" parameterType="Integer"
resultType="com.itheima.po.Customer">
select <include refid="customerColumns"></include>from t_customer where id = #{id}
</select>
相当于select id,username,jobs,phone from t_custome r where id = #{id}
复杂的嵌套格式
思路:嵌套定义查找的表名
from t_customer
对其拆分
<sql id="customerColumns">id,username,jobs,phone</sql>
<sql id="tablename">${prefix}customer</sql>
<sql id="someinclude">from <include refid="${include_target}"></include></sql>
<select id="findCustomerById" parameterType="Integer"
resultType="com.itheima.po.Customer">
select <include refid="customerColumns"></include>
<include refid="someinclude">
<property name="prefix" value="t_"/>
<property name="include_target" value="tablename"/>
</include>
where id = #{id}
</select>
转换之后
select id,username,jobs,phone from t_customer where id = ?
7.2 动态SQL
7.2.1 if元素
就是个判断语句
<select id = "findBynameAndJobs" parameterType="com.itheima.po.Customer"
resultType="com.itheima.po.Customer">
select * from t_customer where 1=1
<if test = "username != null and username != ''">
and username like concat('%',#{username},'%')
</if>
<if test = "jobs != null and jobs != ''">
and jobs like concat('%',#{jobs},'%')
</if>
</select>
值得注意:username != ''与username !=' '(单引号之间加了空格会报错)
select * from t_customer where 1=1 and username like concat('%',?,'%') and jobs like concat('%',?,'%')
7.2.2 choose when otherwise元素
多个选项选择一个选项
</select>
<!-- choose元素 when元素 otherwise -->
<select id = "findBynameOrJobs" parameterType="com.itheima.po.Customer"
resultType="com.itheima.po.Customer">
select * from t_customer where 1=1
<choose>
<when test = "username != null and username != ''">
and username like concat('%',#{username},'%')
</when>
<when test = "jobs != null and jobs != ''">
and jobs like concat('%',#{jobs},'%')
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</select>
当用户名不空时
select * from t_customer where 1=1 and username like concat('%',?,'%')
当用户名为空,职业非空
select * from t_customer where 1=1 and jobs like concat('%',?,'%')
7.2.3where 和 trim 元素
在之前写的语句中,我们会发现都带有 1=1 感觉这个时废话,但是如果去掉的话,生成的SQL语句就会变成了
select * from t_customer where and jobs like concat('%',?,'%')
这样必定会报错了
有没有其他的解决方法呢?
方法一:使用where元素
直接在外面使用where元素包裹即可
select * from t_customer
<where>
<choose>
<when test = "username != null and username != ''">
and username like concat('%',#{username},'%')
</when>
<when test = "jobs != null and jobs != ''">
and jobs like concat('%',#{jobs},'%')
</when>
<otherwise>
and phone is not null
</otherwise>
</choose>
</where>
生成sql
select * from t_customer WHERE jobs like concat('%',?,'%')
方法二:使用trim元素
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
prefix代表语句的前缀
prefixOverrides代表需要去除的那些特殊的字符串
7.2.3 set 元素
用来更新元素,set元素会动态前置set关键字,同时也会自动消除最后一个逗号,set内的元素如果为空会出现sql语法错误。
<update id="updateCustomer" parameterType="com.itheima.po.Customer">
update t_customer
<set>
<if test = "username != null and username != ''">
username = #{username}</if>
<if test = "jobs != null and jobs != ''">
jobs = #{jobs},</if>
<if test = "phone != null and phone != ''">
phone = #{phone},</if>
</set>
where id = #{id}
</update>
update t_customer SET username = ? jobs = ?, phone = ? where id = ?
7.2.4 foreach 元素
用于数组和集合循环遍历
<select id="findByArray" parameterType="List"
resultType="com.itheima.po.Customer">
select * from t_customer
where id in
<foreach collection="list" item="id" index="index"
open="(" separator="," close=")">
#{id}</foreach>
</select>
- item:配置的是循环中当前的元素
- index:配置的是当前元素在集合的位置的下表
- collection:配置的list是传递过来的参数类型(首字母小写)
- open和close:配置的是以什么符号将这些集合元素包装起来
- separator:配置的是各个元素的间隔符
7.2.5 bind 元素
既解决防止动态SQL注入,一方面提高可移植性
直接引用bind元素的name属性值即可进行SQL组装
<select id="findCustomerByName2" parameterType="String"
resultType="com.itheima.po.Customer">
<bind name="pattern_name" value="'%'+username+'%'"/>
select * from t_customer where username like #{pattern_name}
</select>