Mybatis(二)

发布于 2020-12-01  637 次阅读


一,在Mybatis实现CRUD的三种方式

在Mybatis有三种方式实现增删改查分别实现dao,代理dao,注解

一,直接实现dao

直接实现dao就是直接用实现类来调用方法,它也需要写映射文件

MySQL中的表结构:

① map映射文件:

<?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">
<!--namespace:写接口名-->
<mapper namespace="com.wqls.imbwql">
    <select id="wqlfq" resultType="com.wqls.bmswql">
        select  * from bm
    </select>

</mapper>

② 新建实体类:

1,实体类必须和表结构对映,形成映射关系,

2,实现Serializable序列号接口

public class bmswql implements Serializable {
    int id;
    String bmname;

    public void setId(int id) {
        this.id = id;
    }

    public void setBmname(String bmname) {
        this.bmname = bmname;
    }

    public int getId() {
        return id;
    }

    public String getBmname() {
        return bmname;
    }

    @Override
    public String toString() {
        return "bm{" +
                "id=" + id +
                ", bmname='" + bmname + '\'' +
                '}';
    }

}

③ 新键接口类:需要什么操作就写什么方法,注意返回值类

public interface imbwql {
    public List<bmswql> bmsfq();
}

④ 写接口实现类(直接实现dao接口):

public class fqbm  implements  imbwql{
    InputStream a = Resources.getResourceAsStream("mybatisconfig.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(a);
    List<bmswql> aw=null;
    public fqbm() throws IOException {
    }

    public List<bmswql> bmsfq() {
       //sqlid:映射文件中的namespace + 映射ID
        String sqlid="com.wqls.imbwql.wqlfq";
        SqlSession sqlSession = sessionFactory.openSession();
        aw=sqlSession.selectList(sqlid);
        return aw;
    }
}

⑤ 测试:

public static void main(String[] args) throws IOException {

    fqbm a=new fqbm();
    List<bmswql> s=a.bmsfq();
    for(bmswql sd:s){
        System.out.print(sd);
    }

}

结果:

bm{id=1, bmname='市场部'}
bm{id=2, bmname='人力资源部'}
bm{id=3, bmname='安保部'}
bm{id=4, bmname='开发部'}

二,代理dao

代理dao不需要写实现类,提供代理接口,调用代理方法(session.getMapper())帮你实现

① 映射文件:和直接实现dao一样

<?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">
<mapper namespace="com.wqls.imbwql">
    <!--id必须要和接口的方法名一致-->
    <select id="wqlfq" resultType="com.wqls.bmswql">
        select  * from bm
    </select>
</mapper>

② 实体类:和直接实现dao一样,略

 

③接口:和直接实现dao一样,略

 

④ 测试(重点):

public static void main(String[] args) throws IOException {
    //读取主配置文件
    InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml");
    //session工厂创建者(创建者模式:创建工厂)
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    //调用build产生一个Session工厂
    SqlSessionFactory factory = builder.build(inputStream);
    //Session工厂创建一个Sesscee
    SqlSession session = factory.openSession();
    //调用接口代理方式,创建一个代理接口的实现类,
    Iuser iuser=session.getMapper(wqlfq.class);
    //调用代理接口的方法
    List<bmswql> list = iuser.findall();
    for (bmswql a:list){
        System.out.println(a);
}
}

结果:

bm{id=1, bmname='市场部'}
bm{id=2, bmname='人力资源部'}
bm{id=3, bmname='安保部'}
bm{id=4, bmname='开发部'}

三 ,注解实现

关键注解词 : 

@Insert : 插入sql , 和xml insert sql语法完全一样

@Select : 查询sql, 和xml select sql语法完全一样

@Update : 更新sql, 和xml update sql语法完全一样

@Delete : 删除sql, 和xml delete sql语法完全一样

@Param : 入参

@Results : 结果集合
@Result : 结果
实现步骤:

注解实现不需要写映射文件,当要在主配置文件中配置mappers

①不要map映射文件

②实体类一致

③主配置文件:其他不变,只要配置mappers

<mappers>
<!--设置要使用注解的接口,在方法上添加方法-->
<mapper class="com.wqls.imbwql"/>
</mappers>

④ 接口:

public interface imbwql {
    @Select("select * from bm")
    public List<bmswql> select();
}

⑤测试(也需要代理接口):

public static void main(String[] args) throws IOException {

    InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml");
    SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream);
    SqlSession session = sqlSessionFactory.openSession(true);
    imbwql iprople1 = session.getMapper(imbwql.class);
    List<bmswql> ad = iprople1.select();
    for(bmswql s : ad){
        System.out.println(s);
    }
}

四,Mybatis的执行流程

Mybatis的执行流程其实就是Session的产生和销毁

g

①读取主配置文件:Mybatis主要用don4f来进行xml解析

②创建工厂建造者:用到创建者模式,一般工厂的创建都要到这种模式(可以多工厂创建)

③创建工厂:工厂模式,来创建对象

④创建Sqlsession对象:通过Sqlsession可以进行代理操作,和解析读取映射xml文件

⑤创建代理接口对象:Seesion通过Mapper方法构建代理接口实现类

⑥读取解析映射xml文件:对xml解析,反射到实体类上,对象实体类进行映射

⑦通过接口进行一系列的操作

⑧销毁Sqlsession

其实通过这个流程我们可以自定义一个类似于mybatis的功能,之后单独写一遍

二,Mybatis的增删改查(以代理dao方式实现)

Mybatis增删改查其实挺简单,流程和之前的是一致的,只是返回值有不同

一,查(略……)

二,增加

表结构:

① 映射文件

<mapper namespace="com.wql.Iuser">

<insert id="insert" parameterType="com.wql.user">
    insert into fq values (${id},'${name}',${random})
</insert>

</mapper>

② 实体类

public class user implements Serializable {
    int id;
    String name;
    int random;

    public  user(){


    }
    public user(int id, String name, int random) {
        this.id = id;
        this.name = name;
        this.random = random;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setRandom(int random) {
        this.random = random;
    }

    @Override
    public String toString() {
        return "user{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", random=" + random +
                '}';
    }
}

③ 接口

ublic interface Iuser {
//增加数据(插入数据传入对象)
public Boolean insert(user wql);}

④测试

public static void main(String[] args) throws IOException {

    InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

    SqlSessionFactory factory = builder.build(inputStream);

    SqlSession session = factory.openSession();

    Iuser iuser=session.getMapper(Iuser.class);
    Boolean a=iuser.insert(new user(18,"SB",101));
    System.out.print(a);
    session.commit();

结果:

true

三,修改

①实体类(与增加一样,略……)

②映射文件

<mapper namespace="com.wql.Iuser">
<update id="update">
    update fq set name=#{name} where id=#{id}
</update>

</mapper>

③ 接口

ublic interface Iuser {
//修改数据(修改数据传入对象)
public void update(user u);}

④测试

public static void main(String[] args) throws IOException {

    InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

    SqlSessionFactory factory = builder.build(inputStream);

    SqlSession session = factory.openSession();

    Iuser iuser=session.getMapper(Iuser.class);
    iuser.update(new user(18,"LUOQIN",10));
    session.commit();
}}

四,删除

①实体类(一样,略……)

②映射文件

<mapper namespace="com.wql.Iuser">
<!--传入判断字段名的值-->
<delete id="delete" parameterType="Int" >
    delete from fq where id=#{a}
</delete>
</mapper>

③接口

ublic interface Iuser {
//删除数据(修改数据传入id字段的int值) 
public void delect(int u);}

④测试

public static void main(String[] args) throws IOException {

    InputStream inputStream = Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

    SqlSessionFactory factory = builder.build(inputStream);

    SqlSession session = factory.openSession();

    Iuser iuser=session.getMapper(Iuser.class);

         iuser.delete(14);
        session.commit();}}

五,CRUD的细节问题

查询时:只能用javaBean对象进行映射接收所有result所有一般是JavaBean,但也可以有map集合接收单个数据或者多个数据

增加,修改,删除:输入类型也只能是javaBean,返回值一般都用void(无返回),假如是int的话(成功为1,不成功为o),为Boolean时(你懂的)

六,select的三种返回方式

一,javaBean返回(前后都是这种方式,略……)

 

二,Map集合接收单条数据

map接收单条数据,表和map集合产生映射,字段会成为键,字段值会变成value,通过键获取value

表结构:

① 映射文件

<?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">
<mapper namespace="com.fq.iprople">
<!--单条数据映射进Map集合-->
<select id="select3" resultType="Map">
     select * from prople where id=#{a}
</select>
</mapper>

② 实体类

public class prople {

    int id;
    String name;
    int bmid;
    int age;
    String xb;


    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBmid(int bmid) {
        this.bmid = bmid;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setXb(String xb) {
        this.xb = xb;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getBmid() {
        return bmid;
    }

    public int getAge() {
        return age;
    }

    public String getXb() {
        return xb;
    }

    @Override
    public String toString() {
        return "prople{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", bmid=" + bmid +
                ", age=" + age +
                ", xb='" + xb + '\'' +
                '}';
    }
}

③接口

public interface iprople {
//单条数据查询(保存到Map集合)
public Map<String,String> select3(int id);
}

④测试:

   InputStream stream= Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder sessionFactoryBuilder= new SqlSessionFactoryBuilder();

    SqlSessionFactory sqlSessionFactory=sessionFactoryBuilder.build(stream);

    SqlSession session=sqlSessionFactory.openSession(true);

   iprople iprople1= session.getMapper(iprople.class);

    Map<String, String> map=iprople1.select3(1);
    Set set= map.keySet();
    for(Object a:set){
        System.out.println(a);
    }
  

}

结果:

name
bmid
xb
id
age

三,map集合接收多条数据

Map接收多条数据,需要在接口方法上加@MapKey(value = "表字段名"),表明以那个字段为键,value就是JavaBean对象

① 实体类(和上面一样,略……)

②map映射文件

<?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">
<mapper namespace="com.fq.iprople">
<!--多条数据映射进Map集合-->
<select id="select4" resultType="prople">
    select  * from prople;
</select>
</mapper>

③ 接口

public interface iprople {
//4,多条数据查询(保存到Map集合)
    @MapKey(value = "id")//表明以表ID为键
    public  Map<Integer,prople> select4();
}}

④ 测试

public static void main(String[] args) throws IOException {

   InputStream stream= Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder sessionFactoryBuilder= new SqlSessionFactoryBuilder();

    SqlSessionFactory sqlSessionFactory=sessionFactoryBuilder.build(stream);

    SqlSession session=sqlSessionFactory.openSession(true);

   iprople iprople1= session.getMapper(iprople.class);

    Map<Integer, prople> map=iprople1.select4();
    Set set= map.keySet();
    for(Object a:set){
        System.out.println(map.get(a));
    }


}

结果:

prople{id=1, name='WQL', bmid=1, age=23, xb='男'}
prople{id=2, name='张三', bmid=2, age=33, xb='男'}
prople{id=3, name='李四', bmid=4, age=21, xb='男'}
prople{id=4, name='FQ', bmid=2, age=20, xb='女'}

三,Mybatis参数传值方式

主要讲Mybatis参数传值的两种方式

一,参数传值的两种方式${}和#{}

$底层引用的是JDBC的Statement而#底层引用的是JDBC的PreparedStatement,他们自带PreparedStatement和Statement的属性

#:

$:

 

1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:where username=#{username},如果传入的值是111,那么解析成sql时的值为where username="111", 如果传入的值是id,则解析成的sql为where username="id". 
2、$将传入的数据直接显示生成在sql中。
如:where username=${username},如果传入的值是111,那么解析成sql时的值为where username=111;

3、针对上面的sql,如果传入的值是;drop table user;,

那么第一条用#{}的sql解析为:select id, username, password, role from user where username=";drop table user;"

那么第二条用${}的sql解析为:select id, username, password, role from user where username=;drop table user;

这时候已经sql注入了。

3、#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
4、$方式一般用于传入数据库对象,例如传入表名和列名,还有排序时使用order by动态参数时需要使用$ ,ORDER BY ${columnName}
5、一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。
6、在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。

二,传入的参数数量和类型

一,JavaBean作为参数传入

当传入的参数是javaBean对象时:

1,${}:通过${对象属性名获取},但要注意引号问题

2,#{}:和${}一样通过对象属性获取值

不举例

二,单个其他基本类型和包装类参数传值

在Mybatis中非javaBean对象类型的其他数据类下,单个参数传值,会把它封装成一个map集合,有两个键:value,_parameter

例:有一段代码

接口:

public interface fq123 {
    public wql123 select(Integer a);
}

实体类:

public class wql123 implements Serializable {
    Integer id;
    String bmname;

    public void setId(int id) {
        this.id = id;
    }

    public void setBmname(String bmname) {
        this.bmname = bmname;
    }

    public int getId() {
        return id;
    }

    public String getBmname() {
        return bmname;
    }

    @Override
    public String toString() {
        return "bm{" +
                "id=" + id +
                ", bmname='" + bmname + '\'' +
                '}';
    }

map映射文件:我们需要填写的部分

<mapper namespace="com.testsw.fq123">
    <select id="select" resultType="com.testsw.wql123">
        select  * from  bm where id = #{需要填写的部分}

    </select>
</mapper>

#{}和${}对参数的接收:

1,#{}的方式:

① 可以按字段来获取

#{id}

② 可以有任意变量获取

#{随便写}

③用value键来获取参数值

#{value}

④用_parameter键来获取值

#{_parameter}

2,${}的方式:它的方式比#要少,它不能通过字段名和任意去获,只能通过Map的键获取值

① 用value获取参数值

${value}

②用_parameter获取参数值

${_parameter}

三,多个其他基本类型和包装类参数传值

多个和单个其实是一样的,Mybatis也会把多个参数封装进map集合中,只是键有所不同,它根据参数的顺序分为两种

1,arg0,arg1,arg2……

2,param1,param2,……

四,有map集合作为参数传值

之前mybatis间接把参数转化成map集合,我们也可以直接传入map集合,自定义键来取值

例:实体类和接口上面那个案例有

① 映射文件:

<?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">
<!--_parameter-->
<mapper namespace="com.testsw.fq123">
    <select id="select" resultType="com.testsw.wql123">
        select  * from  bm where id = #{wql}

    </select>
</mapper>

② 测试:

public static void main(String[] args) throws IOException {


    InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();

    SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream);

    SqlSession session = sqlSessionFactory.openSession(true);

    fq123 iprople1 = session.getMapper(fq123.class);

    Map map = new HashMap();

    map.put("wql",1);
    wql123 a=iprople1.select(map);
    System.out.println(a);
}

结果:

bm{id=1, bmname='市场部'}

五,通过@param注解来自定义键

mybatis提供了一个@param注解,来实现自定义键

语法:@param("自定义键名称")

案例:实体类是一样的

接口:

public interface fq123 {
    public wql123 select(@Param("WQL") int a);
}

map映射文件:

<?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">
<!--_parameter-->
<mapper namespace="com.testsw.fq123">
    <select id="select" resultType="com.testsw.wql123">
        select  * from  bm where id = ${WQL}

    </select>
</mapper>

测试:

public static void main(String[] args) throws IOException {


    InputStream stream = Resources.getResourceAsStream("mybatisconfig.xml");

    SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();

    SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(stream);

    SqlSession session = sqlSessionFactory.openSession(true);

    fq123 iprople1 = session.getMapper(fq123.class);

    wql123 a=iprople1.select(1);
    System.out.println(a);
}

结果:

bm{id=1, bmname='市场部'}

四,多表关联关系

多表查询依赖多表关联关系,mybatis多表联查和MySQL的设置主外键的方式类似,它提供自定义映射关系来建立表连接,

  多表关联的几种方式:

1,result标签之间设定

2,association设定

3,分步查询

一,resultMap自定义映射

和MySQL多表联查依赖主外键一样,Mybatis多表查询依赖自定义映射,

resultMap的属性:

1,id:映射的标识,自定义

2,type:映射的实体类类型,写全限定类名就行

子标签:

id:设置主键和对象属性的映射

result:设置其他字段和对象属性映射

association:设置映射,也可以设置分步操作

子标签的公共属性:
property:对象的属性名

column:表的字段名

二,使用标准的result做多表查询

两个表的表结构:

实体类:

部门表对映的实体类:

import java.io.Serializable;

public class bmswql implements Serializable {
    int id;
    String bmname;

//set和get方法不显示
    @Override
    public String toString() {
        return "bm{" +
                "id=" + id +
                ", bmname='" + bmname + '\'' +
                '}';
    }

}

员工表对映的实体类:

public class wqluser {
    int id;
    String name;
    int age;
    String xb;
    int bmid;
  //需要关联的表的实体类对象,只是映射的关键
    bm bms;

 //Set和get方法这里不显示了

    @Override
    public String toString() {
        return "wqluser{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", xb='" + xb + '\'' +
                ", bmname=" + bms +
                ", bmid=" + bmid +
                '}';
    }
}

接口:

public interface Iwqluser {

    public List<wqluser> select1();}

映射文件:

<mapper namespace="com.duobiao.Iwqluser">
    <resultMap id="wql" type="com.duobiao.wqluser">
        <id property="id" column="id"/>
        <result  column="name" property="name"/>
        <result  column="age" property="age"/>
        <result column="xb"  property="xb"/>
        <result column="bmid" property="bmid"/>
        <!--其他表的映射-->
        <result column="id" property="bms.id"/>
        <result  column="bmname" property="bms.bmname"/>
              </resultMap>

   <select id="select1" resultMap="wql">
    select prople.id,bm.bmname,prople.name,prople.age,prople.xb,prople.bmid from prople left  join bm on prople.bmid=bm.id
   </select>
</mapper>

二,使用标准的association做多表查询

association的属性:

property:要连接的对象名

javaType:连接对象的java类型,直接写全限定类名

select:要分步的map的id,填其他查询的id

子标签:result功能和上面的一样

其他不变,只是对映射文件就行修改

映射文件:

<mapper namespace="com.duobiao.Iwqluser">
    <resultMap id="wql" type="com.duobiao.wqluser">
        <id property="id" column="id"/>
        <result  column="name" property="name"/>
        <result  column="age" property="age"/>
        <result column="xb"  property="xb"/>
        <result column="bmid" property="bmid"/>
          <!---->
        <association property="bms" javaType="com.duobiao.bm">
            <result column="bmname" property="bmname"/>
            <result column="id" property="id"/>
        </association>
    </resultMap>
<select id="select1" resultMap="wql">
    select prople.id,bm.bmname,prople.name,prople.age,prople.xb,prople.bmid from prople left  join bm on prople.bmid=bm.id
</select>
</Mapper>

三,分步查询

一个查询连接下一个查询,这个操作和下一个操作共同进行

<mapper namespace="com.duobiao.Iwqluser">

 <resultMap id="wqlusers" type="com.duobiao.wqluser">
    <id property="id" column="id"/>
    <result  column="name" property="name"/>
    <result  column="age" property="age"/>
    <result column="xb"  property="xb"/>
    <result column="bmid" property="bmid"/>
<!--property:要连接的对象名(就是员工类里面的bm对象)
    select:下一步要执行的resultMap
    column:以什么属性作为传入参数
-->
    <association property="bms" select="select3" column="bmid"/>
</resultMap>

<resultMap id="bms" type="com.duobiao.bm">
        <result column="id" property="id"/>
        <result  column="bmname" property="bmname"/>
    </resultMap>

   
    <select id="select2" resultMap="wqlusers">
        select id,name,age,xb,bmid from prople where id=#{a}
    </select>
    
    <select id="select3" resultMap="bms">
        select * from bm where id=#{b}
    </select>
</mapper>

五,动态SQL

动态SQL是Mybatis的一个特征

if 标签

if 标签通常用于 WHERE 语句、UPDATE 语句、INSERT 语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。

<if test="name != null and name != ''"> 
and NAME = #{name} 
</if>

foreach 标签

foreach 标签主要用于构建 in 条件,可在 sql 中对集合进行迭代。也常用到批量删除、添加等操作中

<!-- in查询所有,不分页 -->
<select id="selectIn" resultMap="BaseResultMap">
select name,hobby from student where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>

属性介绍:

  • collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
  • item :表示在迭代过程中每一个元素的别名
  • index :表示在迭代过程中每次迭代到的位置(下标)
  • open :前缀
  • close :后缀
  • separator :分隔符,表示迭代时每个元素之间以什么分隔

choose 标签

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis 提供了 choose 元素,按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when
的条件都不满则时,则执行 otherwise 中的 sql。类似于 Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

if 是与(and)的关系,而 choose 是或(or)的关系。

<select id="getStudentListChoose" parameterType="Student" resultMap="BaseResultMap">
     SELECT * from STUDENT WHERE 1=1
    <where>
           <choose>
           <when test="Name!=null and student!='' ">
          AND name LIKE CONCAT(CONCAT('%', #{student}),'%')
         </when>
     <when test="hobby!= null and hobby!= '' ">
AND hobby = #{hobby}
       </when>
   <otherwise>
   AND AGE = 15
       </otherwise>
      </choose>
      </where>
           </select>

路漫漫其修远兮,吾将上下而求索