数据表:
实体类:
一。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 标签很万能,能够指定需要去掉的关键字:
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语句,用法很简单:
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();
}
}