MyBatis框架(8.0)
动态SQL
if语句
所谓的if语句指的是更新或查询语句的时候可以对传入的内容进行判断操作;
1,New.xml文件
<select id="findAllByTitle" parameterType="News" resultMap="NewsResultMap">
SELECT nid,title,pub_date FROM news
<if test="title != null">
WHERE title=#{title}
</if>
</select>
此时如果在调用的时候传入了title的内容,那么就使用限定查询,如果没有传入,则表示查询全部的数据:
2,范例:不传入title执行查询
package cn.mldn.dsql;
import java.util.List;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsFindAllByTitle {
public static void main(String[] args) throws Exception {
List<News> all = MyBatisSessionFactory.getSession().selectList(
"cn.mldn.mapping.NewsNS.findAllByTitle");
System.out.println(all);
MyBatisSessionFactory.close();
}
}
Preparing:SELECT nid ,title,pub_date FROM news;
这个时候的sql语句里面并不存在where,因为没有传递相应的内容(null);
3,传递title内容
package cn.mldn.dsql;
import java.util.List;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsFindAllByTitle {
public static void main(String[] args) throws Exception {
News vo = new News() ;
vo.setTitle("今天中午,田老师请客吃饭!");
List<News> all = MyBatisSessionFactory.getSession().selectList(
"cn.mldn.mapping.NewsNS.findAllByTitle", vo);
System.out.println(all);
MyBatisSessionFactory.close();
}
}
Preparing:SELECT nid ,title,pub_date FROM news WHERE title=?;
此时可以发现,查询语句会更根据传入的值得不同而产生不同的执行效果。
范例:在分页上使用动态sql处理
1,修改New.xml文件
<select id="findAllSplit2" resultMap="NewsResultMap" parameterType="java.util.Map">
SELECT nid,title,pub_date FROM news
<if test="column != null">
WHERE ${column} LIKE #{keyWord}
</if>
LIMIT #{start},#{lineSize} ;
</select>
2,编写调用程序:
package cn.mldn.dsql;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsFindSplit {
public static void main(String[] args) throws Exception {
String column = "title";
String keyWord = "%%";
int currentPage = 1;
int lineSize = 5;
Map<String, Object> map = new HashMap<String, Object>();
map.put("column", column);
map.put("keyWord", keyWord);
map.put("start", (currentPage - 1) * lineSize);
map.put("lineSize", lineSize);
List<News> all = MyBatisSessionFactory.getSession().selectList(
"cn.mldn.mapping.NewsNS.findAllSplit2", map); // 没有强制转换
System.out.println(all);
MyBatisSessionFactory.close();
}
}
传入column的内容:
Preparing:SELECT nid ,title,pub_date FROM news WHERE title LIKE ? LIMIT ?,?;
这种操作相当于给用户带来更多的便利性处理,也相对而言节约了不少代码量;
代码展示:
NEW.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">
<!-- 设置命名空间,可以与不同表的同类型操作进行区分,使用时以“空间名称.id”的方式调用 -->
<mapper namespace="cn.mldn.mapping.NewsNS">
<cache eviction="FIFO" flushInterval="10000" readOnly="true" size="512"/>
<!-- 结果转换映射,一般都会在查询的时候使用 -->
<resultMap type="News" id="NewsResultMap">
<id property="nid" column="nid"/>
<result property="title" column="title"/>
<result property="pubdate" column="pub_date"/>
</resultMap>
<select id="findAllByTitle" parameterType="News" resultMap="NewsResultMap">
SELECT nid,title,pub_date FROM news
<if test="title != null">
WHERE title=#{title}
</if>
</select>
<select id="findAllSplit2" resultMap="NewsResultMap" parameterType="java.util.Map">
SELECT nid,title,pub_date FROM news
<if test="column != null">
WHERE ${column} LIKE #{keyWord}
</if>
LIMIT #{start},#{lineSize} ;
</select>
</mapper>
choose语句
if语句可以进行简单的判断,但是如果要想进行多条件判断,就需要通过choose语句完成。如果传递了nid内容则根据nid内容判断,如果创建了title内容则根据title查询,如果两个都有内容则id和title一起查询。
1,修改New.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">
<!-- 设置命名空间,可以与不同表的同类型操作进行区分,使用时以“空间名称.id”的方式调用 -->
<mapper namespace="cn.mldn.mapping.NewsNS">
<cache eviction="FIFO" flushInterval="10000" readOnly="true" size="512"/>
<!-- 结果转换映射,一般都会在查询的时候使用 -->
<resultMap type="News" id="NewsResultMap">
<id property="nid" column="nid"/>
<result property="title" column="title"/>
<result property="pubdate" column="pub_date"/>
</resultMap>
<select id="findAllChoose" parameterType="java.util.Map" resultMap="NewsResultMap">
SELECT nid,title,pub_date FROM news
<where>
<choose>
<when test="column == 'nid'">
${column}=#{nid}
</when>
<when test="column == 'title'">
${column}=#{title}
</when>
</choose>
</where>
</select>
</mapper>
2,编写调用程序:
package cn.mldn.dsql;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsFindAllChoose {
public static void main(String[] args) throws Exception {
Map<String,String> map = new HashMap<String,String>() ;
map.put("column", "title") ; // 操作的列
map.put("title", "你好") ; // 进行列判断的结果
List<News> all = MyBatisSessionFactory.getSession().selectList(
"cn.mldn.mapping.NewsNS.findAllChoose", map);
System.out.println(all);
MyBatisSessionFactory.close();
}
}
“<where>”标签的作用:如果现在里面的有内容,则使用WHERE子句,如果里面没有内容出现在where子句不出现,这样就可以动态的控制where语句的使用;
foreach语句
在实际开发之中,往往会有些动态循环拼凑的sql的情况,例如:在进行指定范围数据查询的时候往往会使用in进行操作,而在进行in操作的时候内容为:“SELECT * FROM 表 WHERE 字段 IN(内容1,内容2 ,…)”。对于中间的内容应该采用拼凑的方式完成,就可以采用循环处理了;
范例:实现数据的批量查询
1,修改New.xml文件:
<sql id="newsColumn">
nid,title,pub_date
</sql>
<select id="findAllForeach" resultMap="NewsResultMap" parameterType="Integer">
SELECT <include refid="newsColumn"/> FROM news
<where>
nid IN
<foreach collection="array" open="(" close=")" separator="," item="ele">
#{ele}
</foreach>
</where>
</select>
“separator=","”:表示多个数据输出间的分隔符;
“item="ele"”:表示取出的每一个元素,而后这个元素要出现在循环体中;
2,编写调用程序:
package cn.mldn.dsql;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsFindEach {
public static void main(String[] args) throws Exception {
Set<Integer> set = new HashSet<Integer>();
set.add(30);
set.add(40);
set.add(50);
List<News> all = MyBatisSessionFactory.getSession().selectList(
"cn.mldn.mapping.NewsNS.findAllForeach", set.toArray());
System.out.println(all);
MyBatisSessionFactory.close();
}
}
Preparing:SELECT nid ,title,pub_date FROM news WHERE nid IN (?,?,?);
范例:批量删除数据
1,修改New.xml文件:
<select id="doRemoveBatch" parameterType="Integer">
DELETE FROM news
<where>
nid IN
<foreach collection="array" open="(" close=")" separator="," item="ele">
#{ele}
</foreach>
</where>
</select>
2,编写调用程序:
package cn.mldn.dsql;
import java.util.HashSet;
import java.util.Set;
import cn.mldn.util.MyBatisSessionFactory;
public class TestNewsRemoveBatch {
public static void main(String[] args) throws Exception {
Set<Integer> set = new HashSet<Integer>();
set.add(30);
set.add(40);
set.add(50);
System.out.println(MyBatisSessionFactory.getSession().delete(
"cn.mldn.mapping.NewsNS.doRemoveBatch", set.toArray()));
MyBatisSessionFactory.getSession().commit();
MyBatisSessionFactory.close();
}
}
Preparing:DELETE FROM news WHERE nid IN (?,?,?);
可以帮助我们减少许多的重复代码;
set语句
范例:动态设置更新处理
1,修改New.xml文件:
<update id="doUpdateDyn" parameterType="News">
UPDATE news
<set>
<if test="title != null">
title=#{title} ,
</if>
<if test="pubdate != null">
pub_date=#{pubdate]} ,
</if>
</set>
<where>
<if test="nid != null">
nid=#{nid}
</if>
</where>
</update>
2,编写调用程序:
package cn.mldn.dsql;
import cn.mldn.util.MyBatisSessionFactory;
import cn.mldn.vo.News;
public class TestNewsUpdateDyn {
public static void main(String[] args) throws Exception {
News vo = new News();
vo.setNid(30);
vo.setTitle("田老师晚上请大家吃饭!");
System.out.println(MyBatisSessionFactory.getSession().update(
"cn.mldn.mapping.NewsNS.doUpdateDyn", vo));
MyBatisSessionFactory.getSession().commit();
MyBatisSessionFactory.close();
}
}
此时只传递了title和nid.可以发现pub_date的更新不会出现,同时在配置文件中编写语句后面的“,”会自动消失,因为
“< set >”标签的出现。
总结:
MyBatis的动态SQL是它的主要生命力,可以说利用动态SQL的开发才是MyBatis的特色。