接上一节,注意本博客所有的代码都是建立在上一讲之上的,如果你没有上一讲的配置,这一讲代码我推荐你还是看看,直接搭建环境需要你有上一讲配置完毕,否则会出现许多错误,另外本篇并没有完成Mybatis动态SQL拼接的全部,只是举例一部分进行说明,我们在工作上或者实际生活中使用Mybatis,也是给我自己记录笔记,将来可以进行重构,然后慢慢完善。
如果你需要查看上一篇点击这里
废话不多说,我们开始:
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
本文将重点围绕 if 进行介绍
第一步,完善上一篇没完善的代码,创建一个studentInfo的bean对象来实现我们对数据的交互操作。
java
public class StudentInfo {
private Integer sid;//学生id
private String sname;//学生姓名
private Integer cid; //外键管理,类id
private String tel; //电话号码
private String addr;//地址
//添加一个多值传入的方法 在实体类中创建一个List用于存放要删除的sid
private List<Integer> sidList;
public List<Integer> getSidList() {
return sidList;
}
public void setSidList(List<Integer> sidList) {
this.sidList = sidList;
}
public StudentInfo(List<Integer> sidList) {
super();
this.sidList = sidList;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addr == null) ? 0 : addr.hashCode());
result = prime * result + ((cid == null) ? 0 : cid.hashCode());
result = prime * result + ((sid == null) ? 0 : sid.hashCode());
result = prime * result + ((sname == null) ? 0 : sname.hashCode());
result = prime * result + ((tel == null) ? 0 : tel.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentInfo other = (StudentInfo) obj;
if (addr == null) {
if (other.addr != null)
return false;
} else if (!addr.equals(other.addr))
return false;
if (cid == null) {
if (other.cid != null)
return false;
} else if (!cid.equals(other.cid))
return false;
if (sid == null) {
if (other.sid != null)
return false;
} else if (!sid.equals(other.sid))
return false;
if (sname == null) {
if (other.sname != null)
return false;
} else if (!sname.equals(other.sname))
return false;
if (tel == null) {
if (other.tel != null)
return false;
} else if (!tel.equals(other.tel))
return false;
return true;
}
@Override
public String toString() {
return "StudentInfo [sid=" + sid + ", sname=" + sname + ", cid=" + cid + ", tel=" + tel + ", addr=" + addr
+ "]";
}
public StudentInfo(Integer sid, String sname, Integer cid, String tel, String addr) {
super();
this.sid = sid;
this.sname = sname;
this.cid = cid;
this.tel = tel;
this.addr = addr;
}
public StudentInfo() {
super();
}
}
实体bean类,作为我们mybatis的映射文件,注意,本篇和上篇都是简单的进行Mybatis的理解,在正式生产环境会有所差别,本文档并没有十分规范的按照MVC模式进行,故而请各位体谅。
本篇Xml将实现对SQL的动态拼接,完成对SQL语句的动态拼接操作,主要使用的是Mybatis自带的< if test="sname != null">
and sname = #{sname}
< /if > 来操作完成对sql的动态拼接
StudentInfoMapper.xml
xml
<?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 :命名空间 ,就是用来避免命名冲突的,同一个命名空间下面都不能出现相同的id -->
<mapper namespace="StudentInfo">
<!-- mybatis-config.xml 中 <typeAlias type="com.someapp.model.User" alias="User"/> -->
<!-- 写insert delete update select 语句 每一个语句都有一个id,到时候通过命名空间.id 来获取对应的sql语句执行
通过paramenterType 属性来指定这个sql执行语句的参数 通过resultType属性指定这个sql语句后返回值的类型,是每条结果对应的类型 -->
<select id="findAll"
resultType="com.xh.mybatis.bean.StudentInfo">
select sid,sname,cname,tel,addr from classinfo c, stuinfo s
where c.cid = s.cid order by sid asc;
</select>
<!-- 让我们对具体多个值进行查找 -->
<select id="findByValue"
resultType="com.xh.mybatis.bean.StudentInfo">
select sid,sname,tel,addr from stuinfo
<!-- 动态SQL之前,我们先把最艰简单的sql语句添加上来 注意,在条件语句上,我们必须来一个一定成立的条件,方便我们对数据进行读取和判断,或者你确定了用户一定会输入值,否则不要轻易在这里留坑 -->
where sid != 0
<if test="sname != null">
and sname = #{sname}
</if>
<!-- 注意,我这边缺一点东西,就是判断的时候,我们会有一个判断是否存在,的语句,如果存在多余的我还要将其分离出来 注意正确的sql语句书写
and tel = #{tel} , addr = #{addr}是错误的写法 -->
<if test="tel != null and addr != null">
and tel = #{tel} and addr = #{addr}
</if>
order by sid asc;
</select>
<!-- 我觉得动态添加其实没必要,虽然我寻思也有,但是我还是觉得,动态添加真的没必要,毕竟这特么有点反人类,我寻思,让你添加数据,你特么 老老实实给我把数据填写完毕不就行了吗?
还有就是,我们可以在业务层直接处理,在前端传数据过来,我们就可以判断然后将没传的值置空处理 如果你非要做,我给你这个参考一下 数据库支持多行插入
<insert id="insertTable" useGeneratedKeys="true" keyProperty="id" parameterType
= "com.***">
insert into table (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password},
#{item.email}, #{item.bio})
</foreach>
</insert> -->
<insert id="add" parameterType="com.xh.mybatis.bean.StudentInfo">
<!--#{} 采用预编译的方式 ${} 采用字符串拼接的方法 -->
insert into stuinfo values(0,#{sname},#{cid},#{tel},#{addr});
</insert>
<!--接下来就是我们的删除操作了,这个就很简单了,动态删除? 得了吧,我这边给个思路,但是我不做,也就是一次传多个值,然后删除多个值,
1 delete from table where sid in( ${sid} ) 这也是一种方式
<select id="deleteByIds" parameterType="Integer">
delete from accounts where id in
<foreach collection="ids" open="(" close=")"
separator="," item="id"> #{id}
</foreach>
</select>
<delete id="deleteValue"
parameterType="com.xh.mybatis.bean.StudentInfo"> delete from stuinfo where
sid != 0 and sid = #{sid};
</delete> -->
<delete id="deleteValue"
parameterType="com.xh.mybatis.bean.StudentInfo">
delete from stuinfo where cid != 0 and sid = #{sid};
</delete>
<!-- 重头戏来了,我们有些时候会涉及到改操作,但是改操作只对用户的某一个数据进行更改 也可能对多个数据进行更改,故而我们需要判断用户传过来的数据,这个时候就很重要了 -->
<update id="update"
parameterType="com.xh.mybatis.bean.StudentInfo">
update stuinfo set
<if test="sname != null">
sname = #{sname}
</if>
<if test="cid != null">
, cid = #{cid}
</if>
<if test="tel != null">
, tel = #{tel}
</if>
<if test="addr != null">
, addr = #{addr}
</if>
where sid = #{sid};
</update>
</mapper>
至此,XML文件也配置完毕,具体的内容见代码中的注释,单纯是个人的理解,不代表就一定是正确的。
测试类:
java
public class StuTest {
/**
* 查询表中所有数据,studentInfo,先从一个简单的表开始吧,然后逐层加难
* @throws IOException
*/
@Test
public void test1() throws IOException {
//加载mybatis-config.xml配置文件
InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<StudentInfo> cls = sqlSession.selectList("StudentInfo.findAll");
//遍历list中的所有的值
cls.forEach(System.out::println);
sqlSession.commit();
sqlSession.close();
}
/**
* 多值查询
* @throws IOException
*/
@Test
public void test2() throws IOException {
//加载mybatis-config.xml配置文件
InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
//多值查询,为了避免我使用new StudentInfo(****)
StudentInfo stu = new StudentInfo();
//注意,这里我就开始使用动态sql进行判断了
stu.setSname("王老五");
//stu.setTel("15973121101");
//stu.setAddr("湖南衡阳");
//我们查询的时候可以是一个值,也可以是多个值,故而我们通常将查到的值存到集合中,至于是哪种集合,你选择
List<StudentInfo> cls = sqlSession.selectList("StudentInfo.findByValue", stu);
//遍历list中的所有的值
cls.forEach(System.out::println);
sqlSession.commit();
sqlSession.close();
}
/**
* 多值添加
* @throws IOException
*/
@Test
public void test3() throws IOException {
//加载mybatis-config.xml配置文件
InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
//先查询所有数据
List<StudentInfo> cls = sqlSession.selectList("StudentInfo.findAll");
cls.forEach(System.out::println);
StudentInfo stu = new StudentInfo();
stu.setSname("王老五");
stu.setCid(1);
stu.setTel("16682187574");
stu.setAddr("湖南长沙");
int result = sqlSession.insert("StudentInfo.add",stu);
if(result > 0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
//遍历list中的所有的值
sqlSession.commit();
//插入后提交成功之后再次查询
List<StudentInfo> cls1 = sqlSession.selectList("StudentInfo.findAll");
cls1.forEach(System.out::println);
sqlSession.close();
}
//删除
@Test
public void test4() throws IOException {
//加载mybatis-config.xml配置文件
InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
//在删除之前,我们先查询表中数据
List<StudentInfo> cls = sqlSession.selectList("StudentInfo.findAll");
//遍历list中的所有的值
cls.forEach(System.out::println);
StudentInfo stu = new StudentInfo();
//System.out.println(sidList);
//System.out.println(stu.getSidList());
//你要删除的id号
stu.setSid(8);
int result = sqlSession.delete("StudentInfo.deleteValue",stu);
if(result > 0) {
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
sqlSession.commit();
List<StudentInfo> cls1 = sqlSession.selectList("StudentInfo.findAll");
//遍历list中的所有的值
cls1.forEach(System.out::println);
sqlSession.close();
}
//更新,多值
@Test
public void test5() throws IOException {
//加载mybatis-config.xml配置文件
InputStream reader = Resources.getResourceAsStream("mybatis-config.xml");
//创建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
//多值查询,为了避免我使用new StudentInfo(****)
StudentInfo stu = new StudentInfo();
//注意,这里我就开始使用动态sql进行判断了
//cid为空只是因为我没查,不要误会。
stu.setSname("王老六"); //StudentInfo [sid=9, sname=王老六, cid=null, tel=16682187574, addr=湖南长沙]
stu.setCid(2); //更改班级编号,前台条件班级必须存在
stu.setSid(9); //更新语句的条件
stu.setTel("15973121103");
stu.setAddr("湖南衡阳");
// 更新后的数据 StudentInfo [sid=9, sname=王老六, cid=null, tel=15973121103, addr=湖南衡阳]
//我们查询的时候可以是一个值,也可以是多个值,故而我们通常将查到的值存到集合中,至于是哪种集合,你选择
int result = sqlSession.update("StudentInfo.update",stu);
if(result > 0) {
System.out.println("更新成功");
}else {
System.out.println("更新失败");
}
List<StudentInfo> cls = sqlSession.selectList("StudentInfo.findByValue", stu);
cls.forEach(System.out::println);
sqlSession.commit();
sqlSession.close();
}
}
行文至此,本篇结束,但是学习之路还得继续,技术是无限的,这两篇只是了解Mybatis简单使用,在这两篇文中可以使用mybatis框架去完成一个项目的简单增删改查操作。但是这并不能代表你就会了这个框架了,框架底层还有其高级部分,都是我需要去掌握的,只有不断学习才能提高自己的能力,才能在当今这个非常卷的时代闯出一番自己的天地。