Mybatis学习基础篇(二)——使用MyBatis完成对数据库语句的动态添加

接上一节,注意本博客所有的代码都是建立在上一讲之上的,如果你没有上一讲的配置,这一讲代码我推荐你还是看看,直接搭建环境需要你有上一讲配置完毕,否则会出现许多错误,另外本篇并没有完成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框架去完成一个项目的简单增删改查操作。但是这并不能代表你就会了这个框架了,框架底层还有其高级部分,都是我需要去掌握的,只有不断学习才能提高自己的能力,才能在当今这个非常卷的时代闯出一番自己的天地。

相关推荐
陌上花开࿈30 分钟前
调用第三方接口
java
Aileen_0v037 分钟前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
桂月二二2 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
liuxin334455663 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
小马爱打代码3 小时前
设计模式详解(建造者模式)
java·设计模式·建造者模式
栗子~~4 小时前
idea 8年使用整理
java·ide·intellij-idea
2301_801483694 小时前
Maven核心概念
java·maven
Q_19284999064 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
我要学编程(ಥ_ಥ)5 小时前
初始JavaEE篇 —— 网络原理---传输层协议:深入理解UDP/TCP
java·网络·tcp/ip·udp·java-ee
就爱学编程5 小时前
重生之我在异世界学编程之C语言:数据在内存中的存储篇(下)
java·服务器·c语言