Mybatis 之 MyBatis3 的SQL 映射文件与动态SQL
MyBatis 框架是基于SQL 映射的,所以SQL 映射文件在此框架中的位置非常重要.动态SQL 是MyB atis 提供的, 它根据指定的条件来执行指定的SQL 语句, 它使SQL 映射文件中的SQL 语句在执行时具有动态性.
<resultMap >标签
在<select>标签中使用resultMap 属性来引用<resultMap> 的id 属性值,形成映射关系,userinfo对应实体类
<select id="selectAll" resultMap="userinfo">
select * from userinfo order
by
d asc
</select>
<sql>标签
重复的sql语句永远不可避免,<sql>标签就是用来解决这个问题
上面代码中的id 、usemame 、password 、age 和createTime 这5 个字段在映射文件中多处出现,所以可以将这5 个字段封装进<sql>标签中, 以减少配置的代码量
<sql id="userinfoColumn">id "id",username "username",password,age,createTime</sql>
<select id="selectAll" resultType="entity.Userinfo">
select
<include refid="userinfoColumn"></include>
from userinfo order
by id asc
</select>
使用${ }拼接SQL 语句
在MyBatis 中也支持将SQL 语句当成变量传入
( 在SQL 语句中出现< 小于或者是<= 小于等于的条件时, 由于<符号是特殊的符号,所以要使用<![CDATA[ ]]>将其转化成为普通的字符串)
<select id="getUserinfo" parameterType="map" resultType="entity.Userinfo">
select id,username,password,createTime
from userinfo where id <![CDATA[<]]>
#{userId}
order by ${orderSQL}
</select>
public static void main(String[] args) throws IOException {
Map map = new HashMap();
map.put("userId",1);
map.put("orderSQL", " id desc");
SqlSession session = GetSqlSession.getSqlSession();
UserinfoMapper mapper = session.getMapper(UserinfoMapper.class);
List<Userinfo> listUserinfo = mapper.selectAll(map);
for (int i = 0; i < listUserinfo.size(); i++) {
Userinfo userinfo = listUserinfo.get(i);
}
session.commit();
session.close();
}
插入null 值时的处理
1. 在#{ } 格式中加入了数据类型的声明, 这样可以明确地告诉MyBatis 框架遇到null 值该如何处理。
<insert id="insertUserinfo" parameterType="entity.Userinfo">
insert into userinfo(id,username,password,age,createTime)
values(
#{id,jdbcType=INTEGER},
#{username,jdbcType=VARCHAR},
#{password,jdbcType=VARCHAR},
#{age,jdbcType=INTEGER},
#{createTime,jdbcType=TIMESTAMP})
</insert>
2. 使用动态SQL 标签解决
<insert id="insertUserinfo" parameterType="entity.Userinfo">
insert into userinfo(id,username,password,
<if test="age!=null and age!=' '">
age,
</if>
createTime)
values(
#{id},#{username},#{password}
<if test="age!=null and age!=' '">
,#{age}
</if>
,#{createTime})
</insert>
<where>标签
where 的主要作用就是生成根据条件查询的SQL 语句,,可以用在增删改查
<select id="selectAll" parameterType="map" resultType="entity.Userinfo">
select * from userinfo
<where>
<if test="username!=null">username like #{username}</if>
<if test="password!=null">and password like #{password}</if>
</where>
</select>
<choose>标签
类似于Java 语言中的switch
<select id="selectAll" parameterType="map" resultType="entity.Userinfo">
select * from userinfo where 1=1
<choose>
<when test="username!=null"> and username like #{username}</when>
<when test="password!=null"> and password like #{password}</when>
<otherwise>and age=100</otherwise>
</choose>
</select>
<set>标签
用在update 语句中,动态指定要更新的列
<update id="updateUserinfoById" parameterType="map">
update userinfo
<set>
<if test="username!=null and username!=' '">username=#{username},</if>
<if test="password!=null and password!=' '">password=#{password},</if>
<if test="age!=null and age!=' '" >age=#{age},</if>
<if test="createTime!=null and createTime!=' '">createTime=#{createTime}</if>
</set>
where id=#{id}
</update>
<foreach>标签
<foreach >标签有循环的功能,可以用来生成有规律的SQL 语句,主要的属性有item 、index 、collection、open 、separator 和close.item 表示集合中每一个元素进行迭代时的别名, index 指定一个名字,用于表示在迭代过程中每次迭代到的位置, open 表示该语句以什么开始, separator 表示在每次迭代之间以什么符号作为分隔符, close 表示该语句以什么结束。
<select id="selectAll" parameterType="map" resultType="entity.Userinfo">
select *
from userinfo where id in
<foreach item="eachId" collection="list" open="("
separator="," close=")">
#{eachId}
</foreach>
</select>
使用<bind>标签对like 语句进行适配
在SQL 语句中使用like 查询时,
MySQL 在拼接字符串时使用concat( )方法,
Oracle 却使用 || 运算符,两者的SQL 语句并不相同,这就要创建2 个SQL 映射语句
这时可以使用<bind>标签在多个数据库之间进行适配
<select id="selectAll1" parameterType="string" resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+_parameter+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<select id="selectAll2" parameterType="entity.Userinfo"
resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+_parameter.getUsername()+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<select id="selectAll3" parameterType="entity.Userinfo"
resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+username+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<select id="selectAll4" parameterType="entity.Userinfo"
resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+_parameter.username+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<select id="selectAll5" parameterType="entity.Userinfo"
resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+#root._parameter.username+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<select id="selectAll6" parameterType="map" resultType="entity.Userinfo">
<bind name="querySQL" value="'%'+username+'%'" />
select * from userinfo where username like #{querySQL}
</select>
<bind>标签的value 属性值中的运算是使用OGNL 表达式, OGNL 表达式的底层是使用Java语言, 所以在Java 语言中可以直接使用+号进行字符串的拼接, 并不像在Oracle 或 MySQL 中要使用 || 或concat( )
对查询的数据进行分页
MyBatis 提供的分页功能在执行效率上是比较差的,它的算法是先将数据表中符合条件的全部记录放入内存,然后在内存中进行分页,这样对内存占用率较高,所以可以参考第三方的MyBatis 分页插件来优化分页执行的效率.
批处理SQL 语句
sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);