MyBatis -- 动态SQL

数据表:

实体类:


一。XML的实现方式。

1.if、where标签
    映射接口的方法:
  /**
     * 根据条件查询Student 
     * @param student 
     * @return 
     */

      public List<Student> queryStudent(Student student);

现在有个多条件查询的需求,根据student中有效的参数动态组装SQL语句,比如
名字和地址不为空,就根据名字和地址组合查询:
select  * from student where sname like '%张%' and address like '%深圳%'
    
如果只有地址,就按照地址查:
select  * from student where sname like '%张%' and address like '%深圳%'
    无论有哪些参数,都能够组合出有效的SQL语句,有条件的包含where子句的一部分。 这就是
     动态SQL通常要做的事情,可以用if和where组合起来实现这个需求:
<select id="queryStudent" resultType="student">
    select * from student
    <where>
        <if test="sName != null">
            and sname like '%${sName}%'
            </if>
	<if test="address != null">
            and address like '%${address}%'
	</if>
    </where>
</select>
    where 标签把需要动态组合的条件包含起来,在if标签中判断Bean属性是否为空即可。
    where标签会自动判断主SQL中有没有where关键字,如果没有则追加一个,同时会把条件的
    第一个and去掉。

    测试方法:
@Test

    public void queryStu1() throws IOException{

            SqlSession session = getSession();

            StudentMapper mapper = session.getMapper(StudentMapper.class);

            

            Student student = new Student();

            student.setsName("张");

            student.setAddress("深圳");

            List<Student> stuList = mapper.queryStudent(student);

            for (Student stu : stuList) {

                    System.out.println(stu);

            }

    }
输出结果:


 2. choose when otherwise
  和Java的switch case default一样的用法。

映射方法
/**
 * 根据性别查询学生,1 男 0 女 
 * @param gender 
 * @return 
 */
 public List<Student> queryStudentByGender(@Param("gender") Integer gender);
注意:如果方法的参数不是个JavaBean,那么请加上个Param注解给参数取别名,然后根据
 别名来访问。否则在标签中直接使用参数名访问时会报错:
 There is no getter for property named 'xx' in 'class java.lang.Integer'。
 因为标签中取数据是要根据传入参数(JavaBean)中的getter方法取,没有getter就报错咯。

 映射文件中的标签
<select id="queryStudentByGender" resultType="student">
    select * from student where gender = 
    <choose>
            <when test="gender != null">
                ${gender}
            </when>
            <otherwise>
                1
            </otherwise>
    </choose>
</select>
不为空则根据传入的值查,为空则查所有男生。

测试方法:
@Test
public void queryStu2() throws IOException{
    SqlSession session = getSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    List<Student> stuList = mapper.queryStudentByGender(null);
    for (Student stu : stuList) {
            System.out.println(stu);
    }
}
输出结果:


3.trim
    trim 标签很万能,能够指定需要去掉的关键字:
<select id="queryStudent" resultType="student">
    select * from student 
    <trim prefix="where" prefixOverrides="and ">
            <if test="sName != null">
                    and sname like '%${sName}%'
            </if>
            <if test="address != null">
                    and address like '%${address}%'
            </if>
    </trim>
</select>
trim标签有前缀、覆盖前缀、后缀、覆盖后缀四个属性,prefix表示前缀,prefixOverrides表
示覆盖前缀。这个例子中如果if如果条件通过,就把覆盖前缀替换成prefix中的值。 也就是第
一个 and 会被 替换成 where 。这样也能够达到where + if 的效果。

prefix:配置的值会被添加到SQL语句开始的地方
prefixOverrides:SQL语句出现的参数会被覆盖

后缀和覆盖后缀也是同理,反过来思考就OK了。


4.set
 set用于update 语句,根据参数确定需要update的列,动态拼接SQL语句,用法很简单:
<update id="updateStudent">
    update student
    <set>
        <if test="sName != null">
                sname = #{sName},
        </if>
        <if test="age != null">
                age = #{age},
        </if>
        <if test="address != null">
                address = #{address}
        </if>
    </set>
    where sid = #{sId}
</update>
5.foreach
foreach语句一般的是用于构建动态的 IN 条件语句,比如  
select * from student where age in (18 , 19 , 20); 18,19,20并不是固定的,
条件有多个,那么传递过来的参数肯定是个数组或者list,foreach标签就能够遍历之,
不过括号、逗号等需要通过它提供的属性来指定。不多BB,看一下你就懂了:

映射方法:
@Test
public void queryByAge() throws IOException {

        SqlSession session = getSession();

        StudentMapper mapper = session.getMapper(StudentMapper.class);
        List<Integer> ageList = new ArrayList<>();

        ageList.add(18);
        ageList.add(19);
        ageList.add(21);
        

        List<Student> list = mapper.queryStudentByAnyAge(ageList);

        for (Student student : list) {
                System.out.println(student);

        }
}
二。注解的实现方式

通过Provider注解实现:
public interface StudentMapper {

static class StudentProvider{

    /**         
    * 提供SQL语句的方法,返回值是经处理过的SQL语句         
    * @param map 对应方法中的参数自动会填充到这个map中,         
    * 根据定义的别名去取即可。         
    * @return         
    */

    public String queryStu(Map<String , Student> map){
            Student student = map.get("stu");
            String sql = "select * from student where 1 = 1 ";
            if (student.getsName() != null && !"".equals(student.getsName())) {
                  sql += " and sname like '%" + student.getsName() + "%'";

                  /*
                  *要注意的是 ${} 这种方式在这是无效的,动态SQL要么拼接要么用下面这种方式
                  * student.setsName("%" + student.getsName() + "%");                       
                  *                          
                  * 注意:要用别名.属性名的方式访问                         
                  * sql += " and sname like #{stu.sName}";                         
                  */

            } else if (student.getAddress() != null && !"".equals(student.getAddress())) {

                    sql += " and address like '%" + student.getAddress() + "%'";
            }
            return sql;

    }

}

/** 
* 根据条件查询Student 
* @param student 
* @return  
*/

@SelectProvider(type = StudentProvider.class, method = "queryStu")
public List<Student> queryStudent(@Param("stu") Student student);

}
type = 提供SQL语句的自定义的Provider.class,上边自定义的内部类。
method = 对应的方法,注意这个方法返回值得是String类型的SQL语句哦。    
CRUD都有对应的注解,比如UPDATE 就叫 @UpdateProvider,这里就不一一列举了。

还有一种用SQL对象拼接SQL语句的玩法:
public String queryStudent(Map<String , Student> map){
        Student student = map.get("stu");
        SQL sql = new SQL().SELECT("*").FROM("student");

        if (student.getsName() != null && !"".equals(student.getsName())) {
                        student.setsName("%" + student.getsName() + "%");
                sql.WHERE("sname like #{stu.sName}");

        } 

       
        if (student.getAddress() != null && !"".equals(student.getAddress())) {
                student.setAddress("%" + student.getAddress() + "%");
                sql.AND();
                sql.WHERE("address like #{stu.address}");
        }
        return sql.toString();
}

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值