MyException - 我的异常网
当前位置:我的异常网» 操作系统 » 0064 MyBatis动态SQL-choose-when-otherwise-foreac

0064 MyBatis动态SQL-choose-when-otherwise-foreach-set-bind

www.MyException.Cn  网友分享于:2013-04-21  浏览:0次
0064 MyBatis动态SQL--choose-when-otherwise--foreach--set--bind

读写数据库的时候,往往要根据传入的参数的不同,改变sql语句。
比如:如果传入了某个参数值,那就查询对应的字段,没传入,那就不查,这就是0048中的where--if
再比如:

  1. 如果传入了某个参数值,那就只查询这个字段,如果没传入,就看下一个字段是否传入,如果这些字段值都没有传入,那就按默认的条件查询。这是choose--when--otherwise
  2. update操作的时候,如果传入了某个参数值,那就更新该字段,如果没传入那就不更新该字段。这是set
  3. 如果要用in查询将某个集合中相关的数据都查出来,这就要foreach
  4. 如果程序传进来的参数值,还需要进一步拼接,这就要bind

choose--when--otherwise

查询书籍信息,如果传入了isbn号,那就只查这个字段,没传入的话,就看书名,有的话就查书名,如果isbn和书名都没有,那就把douban评分大于7分的查出来.
类似于switch,选择一条执行

<mapper namespace="net.sonng.mbt.mapper.BookMapper">
    <select id="findBooks" parameterType="net.sonng.mbt.entity.Book" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE 
            <choose>
                <when test="isbn!=null" > <!-- 如果传入了isbn号,那就只按isbn查 -->
                    isbn=#{isbn}
                </when>
                <when test="name!=null">   <!-- 如果没传入isbn号,就看是否有书名,有的话就只按书名查 -->
                    `name`=#{name}         <!-- 注意name貌似是mysql的关键字,用上横(上划线)括起来 -->
                </when>
                <otherwise>           <!-- 如果isbn和书名都没有,就将douban>7的书籍查出来 -->
                    douban>7     <!-- 实践证明,大于号>在这里可以正常用,换成转移字符:&gt;,也能用 -->
                </otherwise>
            </choose>
    </select>
</mapper>

BookMapper.java接口略
测试类:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

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 BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        Book book=new Book();
        book.setName("深入理解Java 7 核心技术与最佳实践");
        book.setPress("机械工业出版社");
        book.setAuthor("成富著");
        book.setDouban(6.9f);
        book.setIsbn("9787111380399");                  //传入了isbn
        List<Book> books=bookMapper.findBooks(book);
        for(Book b:books){
            System.out.println(b);
        }
    }
}

输出如下:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE isbn=?   //传入了isbn就只按isbn查
DEBUG [main] - ==> Parameters: 9787111380399(String)
DEBUG [main] - <==      Total: 1
Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9]

book.setIsbn("9787111380399");注释掉,输出如下:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE `name`=?         //没有isbn,有name,就只按name查
DEBUG [main] - ==> Parameters: 深入理解Java 7 核心技术与最佳实践(String)
DEBUG [main] - <==      Total: 1
Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=6.9]

book.setName("深入理解Java 7 核心技术与最佳实践");注释掉,输出如下:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE douban>7   //isbn和书名都没有,就把douban>7的列出了,下面有3条查询结果
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 3
Book [id=1, name=深入理解Java虚拟机 JVM高级特性与最佳实践, press=机械工业出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=疯狂Java讲义 第3版, press=电子工业出版社, author=李刚著, isbn=9787121236693, douban=7.8]
Book [id=4, name=Java编程思想 第4版, press=机械工业出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]

set

更新一条书籍信息,可能更新name、press、isbn、author、douban的一个或多个

    <select id="findBookById" parameterType="int" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE id=#{id}
    </select>
    <update id="updateBook" parameterType="net.sonng.mbt.entity.Book" >
        UPDATE book 
        <set>  <!-- set跟where的作用类似 -->
            <if test="name!=null" >`name`=#{name},</if>
            <if test="press!=null" >press=#{press},</if>
            <if test="author!=null" >author=#{author},</if>
            <if test="isbn!=null" >isbn=#{isbn},</if>
            <if test="douban!=null" >douban=#{douban}</if>
        </set>
        WHERE id=${id}
    </update>

测试类:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

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 BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        Book book=bookMapper.findBookById(5);   //update的时候,一般先将数据查出来再修改数据再更新
        book.setDouban(10.0f);
        bookMapper.updateBook(book);
        session.commit();             //注意不要忘了提交事务
        session.close();
    }
}

foreach

用in查询的时候,传入的参数个数不明确,这时候就用foreach进行遍历

    <select id="findBookInId" parameterType="list" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE id In 
        <foreach item="id" index="i" collection="list" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

测试类:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

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 BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        List<Integer> ids=new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(5);
        List<Book> books=bookMapper.findBookInId(ids);
        for(Book book:books){
            System.out.println(book);
        }
        session.close();
    }
}

输出如下:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE id In ( ? , ? , ? ) 
DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer), 5(Integer)
DEBUG [main] - <==      Total: 3
Book [id=1, name=深入理解Java虚拟机 JVM高级特性与最佳实践, press=机械工业出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=疯狂Java讲义 第3版, press=电子工业出版社, author=李刚著, isbn=9787121236693, douban=7.8]
Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

foreach元素的几个属性:
----item:迭代元素的别名
----index:指定一个名字,用于表示在迭代过程中,每次迭代到的位置
----collection:传进来的参数的类型:list(单参数且参数类型为List)、array(单参数且参数类型为数组)、map(多参数)
----open:in后面的语句以什么开始
----separator:元素间的分隔符
----close:in后面的语句以什么结束

bind

该元素从OGNL表达式创建一个变量并将其绑定到上下文

    <select id="findBookLikeName" parameterType="string" resultType="net.sonng.mbt.entity.Book">
        <bind name="pattern" value="'%'+_parameter+'%'" />   <!-- 传进来的参数是java,这里将其拼接成:%java% -->
        SELECT * FROM book WHERE `name` LIKE #{pattern}
    </select>

测试类:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

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 BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        List<Book> books=bookMapper.findBookLikeName("java");
        for(Book book:books){
            System.out.println(book);
        }
        session.close();
    }
}

输出:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE `name` LIKE ? 
DEBUG [main] - ==> Parameters: %java%(String)   //传入的参数是拼接后的字符串
DEBUG [main] - <==      Total: 4
Book [id=1, name=深入理解Java虚拟机 JVM高级特性与最佳实践, press=机械工业出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=疯狂Java讲义 第3版, press=电子工业出版社, author=李刚著, isbn=9787121236693, douban=7.8]
Book [id=4, name=Java编程思想 第4版, press=机械工业出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]
Book [id=5, name=深入理解Java 7 核心技术与最佳实践, press=机械工业出版社, author=成富著, isbn=9787111380399, douban=10.0]

bind的value属性:
----_parameter:注意下划线,表示传进来的参数本身
----parameter:没有下划线,表示传进来的参数的parameter属性
----_parameter.getName():注意下划线,表示调用传进来的参数对象的getName()方法的返回值

小结

if:传进来的某个参数不为空,那么查询该字段
where:可以动态的处理and和,
choose--otherwise:从前往后,哪个参数传进来了,那就只查询该参数,否则按otherwise查询
set:用于update语句,跟where作用类似
foreach:多用于IN查询,用于迭代传进来的参数集合
bind:将传进来的参数进行一些修改

这个文档可以看看:https://www.kancloud.cn/digest/andyalien-mybatis/190191

文章评论

做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
我是如何打败拖延症的
我是如何打败拖延症的
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
 程序员的样子
程序员的样子
总结2014中国互联网十大段子
总结2014中国互联网十大段子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
中美印日四国程序员比较
中美印日四国程序员比较
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
如何成为一名黑客
如何成为一名黑客
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员都该阅读的书
程序员都该阅读的书
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
每天工作4小时的程序员
每天工作4小时的程序员
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
旅行,写作,编程
旅行,写作,编程
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
一个程序员的时间管理
一个程序员的时间管理
漫画:程序员的工作
漫画:程序员的工作
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
我的丈夫是个程序员
我的丈夫是个程序员
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
鲜为人知的编程真相
鲜为人知的编程真相
10个调试和排错的小建议
10个调试和排错的小建议
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Java程序员必看电影
Java程序员必看电影
程序员必看的十大电影
程序员必看的十大电影
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员和编码员之间的区别
程序员和编码员之间的区别
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员应该关注的一些事儿
程序员应该关注的一些事儿
为什么程序员都是夜猫子
为什么程序员都是夜猫子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
那些争议最大的编程观点
那些争议最大的编程观点
程序员的鄙视链
程序员的鄙视链
代码女神横空出世
代码女神横空出世
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有