(3)MyBatis之动态SQL

1.引言

      动态SQL也就是说SQL语句不确定,我们需要根据情况产生SQL语句,那么在什么情况下会用到动态SQL呢?比如我们查询Student时,传入一个student对象,student对象有三个属性(id,name,sal),如果我们想根据id查询student,那么我们的SQL语句为:select * from student where id=#{id},如果我想根据idname字段查询,那么我们生成的SQL语句为:select * from student where id=#{id} and name=#{name},很显然这两个SQL语句是完全不同的,在MyBatis中如果我们使用动态SQL那么就可以用一条语句实现。

2.配置log4j

      为了方便查看我们输出的SQL语句,我们利用log4j输出我们的SQL语句。

  • POM.XML依赖jar
 <dependencies>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.2.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
    </dependency>
  </dependencies>
  • 配置log4j文件
log4j.rootLogger=debug,stdout,logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3 MyBatis之动态SQL

3.1 MyBatis动态SQL之查询(通过自定义对象Student

  • 编写我们的SQL语句
<select id="findAllByObject" parameterType="com.Student" resultMap="studentMap">
    select * from student
    <where>
      <if test="id!=null">
        and id = #{id}
      </if>
      <if test="name!=null">
        and name = #{name}
      </if>
      <if test="sal!=null">
        and sal = #{sal}
      </if>
    </where>
  </select>
  • 编写第一个测试类(通过idname查询)
    @Test
    public void testSelectByIdAndName()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Student s=new Student();
            s.setId(2);
            s.setName("zlr");
            sqlSession.selectList("mynamespace.findAllByObject", s);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 第一个测试类生成的SQL语句

这里写图片描述

  • 第二个测试类(只通过id查询)
    @Test
    public void testSelectById()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Student s=new Student();
            s.setId(2);
            sqlSession.selectList("mynamespace.findAllByObject", s);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 第二个测试类生成的SQL语句

这里写图片描述

  • 代码解释
这个代码注意三点:
    1.两个测试类都是调用的同一个SQL语句(mynamespace.findAll)
    2.两个测试类唯一的不同是new的student对象不一样
        创建的第一个对象拥有idname属性
        创建的第二个对象只拥有id属性
    3.动态SQL if语句前面都有一个and,但是MyBatis框架会自动删除第一个and

3.2 MyBatis动态SQL之查询(通过Map对象)

  • 编写SQL语句
<select id="findAllByMap" parameterType="map" resultMap="studentMap">
    select * from student
    <where>
      <if test="id!=null">
        and id = #{id}
      </if>
      <if test="name!=null">
        and name = #{name}
      </if>
      <if test="sal!=null">
        and sal = #{sal}
      </if>
    </where>
  </select>
  • 编写测试类
    @Test
    public void testSelectByMap()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Map map=new HashMap();
            map.put("id", 1);
            List<Student> students =sqlSession.selectList("mynamespace.findAllByMap", map);
            System.out.print(students);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 自动生成的SQL语句

这里写图片描述

3.3 MyBatis动态SQL之更新(通过Student对象)

  • 编写SQL语句
 <update id="dynaUpdate" parameterType="com.Student">
    update student
    <set>
      <if test="name!=null">
        name = #{name},
      </if>
      <if test="sal!=null">
        sal = #{sal},
      </if>
    </set>
    where id = #{id}
  </update>
  • 编写测试类
    @Test
    public void testUpdate()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Student s=new Student();
            s.setId(2);
            s.setName("wpx");
            sqlSession.update("mynamespace.dynaUpdate", s);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 自动生成的SQL语句

这里写图片描述

  • 数据库的改变

这里写图片描述

  • 代码解释
这个代码主要注意一个地方:
    set语句后面都有一个逗号
    mybatis会自动删除最后一个条件的逗号

3.4 MyBatis动态SQL之删除(通过List对象)

  • 编写SQL语句
<delete id="dynaDeleteList">
    delete from student where id in
    <foreach collection="list" open="(" close=")" separator="," item="ids">
      #{ids}
    </foreach>
  </delete>
  • 编写测试类
    @Test
    public void testDeleteByList()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            List<Integer> ids=new ArrayList<Integer>();
            ids.add(1);
            sqlSession.update("mynamespace.dynaDeleteList", ids);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 自动生成的SQL语句

这里写图片描述

  • 代码解释
<foreach collection="list" open="(" close=")" separator="," item="ids">
            #{ids}
</foreach>
collection:代表我们传入的是list类型
open:表示开始符号
close:表示结束符合
separator:分隔符
item:表示迭代的数组,属性值可以任意,但提倡与方法的数组名相同
#{ids}:表示数组中的每个元素值

3.5 MyBatis动态SQL之删除(通过Array数据)

  • 编写SQL语句
  <delete id="dynaDeleteArray">
    delete from student where id in
    <foreach collection="array" open="(" close=")" separator="," item="ids">
      #{ids}
    </foreach>
  </delete>
  • 编写测试类
    @Test
    public void testDeleteByArray()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Integer []ids=new Integer[1];
            ids[0]=2;
            sqlSession.update("mynamespace.dynaDeleteArray", ids);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 自动生成的SQL语句

这里写图片描述

3.6 MyBatis动态SQL之插入

      动态SQL的插入是最麻烦的,需要利用SQL片段来实现,同时MyBatis也不会自动的帮我们去掉逗号,这都需要我们自己来处理。

  • 首先我们创建SQL片段
   <sql id="key">
        <trim suffixOverrides=",">
            <if test="id!=null">
                id,
            </if>
            <if test="name!=null">
                name,
            </if>
            <if test="sal!=null">
                sal,
            </if>
        </trim>
</sql>
<sql id="value">
    <trim suffixOverrides=",">
      <if test="id!=null">
        #{id},
      </if>
      <if test="name!=null">
        #{name},
      </if>
      <if test="sal!=null">
        #{sal},
      </if>
    </trim>
  </sql>
  <insert id="dynaInsert" parameterType="com.Student">
    insert into student(<include refid="key"/>) values(<include refid="value"/>)
  </insert>
  • 创建测试类
    @Test
    public void testInsert()
    {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try{
            Student s=new Student();
            s.setId(2);
            s.setName("wpx");
            sqlSession.insert("mynamespace.dynaInsert", s);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            sqlSession.commit();
        }
        MyBatisUtil.closeSqlSession();
    }
  • 自动生成的SQL语句

这里写图片描述

  • 代码解释
这个代码需要注意四点
    1.使用<sql>定义sql片段,id属性任意,主要用于insert时的引用
    2.<sql>片段中的if语句可以直接引用insert对象的属性值
    3.使用<trim>去掉sql语句的最后一个逗号
    4.<include refid="key"/>引用我们自定义的<sql>片段

4.代码下载

本博客中的代码下载地址为:MyBatis之动态SQL

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值