目录
1.动态SQL语句
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
1.1 if
需要判断的时候,条件写在test中
<select id="selectListIf" parameterType="user" resultMap="BaseResultMap" >
select
<include refid="baseSQL"></include>
from t_user
<where>
<if test="id != null">
and id = #{id}
</if>
<if test="userName != null">
and user_name = #{userName}
</if>
</where>
</select>
1.2 choose
需要选择一个条件的时候
<!-- choose 的使用 -->
<select id="selectListChoose" parameterType="user" resultMap="BaseResultMap" >
select
<include refid="baseSQL"></include>
from t_user
<where>
<choose>
<when test="id != null">
id = #{id}
</when>
<when test="userName != null and userName != ''">
and user_name like CONCAT(CONCAT('%',#{userName,jdbcType=VARCHAR}),'%')
</when>
<otherwise>
</otherwise>
</choose>
</where>
</select>
1.3 trim
需要去掉where、and、逗号之类的符号的时候
<!--
trim 的使用
替代where标签的使用
-->
<select id="selectListTrim" resultMap="BaseResultMap"
parameterType="user">
select <include refid="baseSQL"></include>
<!-- <where>
<if test="username!=null">
and name = #{username}
</if>
</where> -->
<trim prefix="where" prefixOverrides="AND |OR ">
<if test="userName!=null">
and user_name = #{userName}
</if>
<if test="age != 0">
and age = #{age}
</if>
</trim>
</select>
<!-- 替代set标签的使用 -->
<update id="updateUser" parameterType="User">
update t_user
<trim prefix="set" suffixOverrides=",">
<if test="userName!=null">
user_name = #{userName},
</if>
<if test="age != 0">
age = #{age}
</if>
</trim>
where id=#{id}
</update>
1.4 foreach
需要遍历集合的时候
<delete id="deleteByList" parameterType="java.util.List">
delete from t_user
where id in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id,jdbcType=INTEGER}
</foreach>
</delete>
动态SQL主要是用来解决SQL语句生成的问题。
2.批量操作
我们在项目中会有一些批量操作的场景,比如导入文件批量处理数据的情况(批量新增商户、批量修改商户信息),当数据量非常大,比如超过几万条的时候,在Java代码中循环发送SQL到数据库执行肯定是不现实的,因为这个意味着要跟数据库创建几万次会话。即使在同一个连接中,也有重复编译和执行SQL的开销。
例如循环插入10000条(大约耗时3秒钟):
public class Test03Batch {
public SqlSession session;
@Before
public void init() throws IOException {
// 1.获取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.加载解析配置文件并获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 3.根据SqlSessionFactory对象获取SqlSession对象
session = factory.openSession();
}
/**
* 循环插入10000
*/
@Test
public void test1(){
long start = System.currentTimeMillis();
UserMapper mapper = session.getMapper(UserMapper.class);
int count = 12000;
for (int i=2000; i< count; i++) {
User user = new User();
user.setUserName("a"+i);
mapper.insertUser(user);
}
session.commit();
session.close();
long end = System.currentTimeMillis();
System.out.println("循环批量插入"+count+"条,耗时:" + (end -start )+"毫秒");
}
}
在MyBatis里面是支持批量的操作的,包括批量的插入、更新、删除。我们可以直接传入一个List、Set、Map或者数组,配合动态SQL的标签,MyBatis会自动帮我们生成语法正确的SQL语句。
2.1 批量插入
批量插入的语法是这样的,只要在values后面增加插入的值就可以了。
insert into tbl_emp (emp_id, emp_name, gender,email, d_id) values ( ?,?,?,?,? ),( ?,?,?,?,? ),( ?,?,?,?,? )
在Mapper文件里面,我们使用foreach标签拼接 values部分的语句:
<!-- 批量插入 -->
<insert id="insertUserList" parameterType="java.util.List" >
insert into t_user(user_name,real_name)
values
<foreach collection="list" item="user" separator=",">
(#{user.userName},#{user.realName})
</foreach>
</insert>
Java代码里面,直接传入一个List类型的参数。
/**
* 批量插入
*/
@Test
public void test2(){
long start = System.currentTimeMillis();
UserMapper mapper = session.getMapper(UserMapper.class);
int count = 12000