Mybatis入门案例

这篇博客详细介绍了Mybatis的入门案例,包括占位符的使用、优化技巧、动态SQL标签的讲解,以及Mapper接口和注解开发的实践,是学习Mybatis的全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Mybatis入门案例

--查询yonghedb.emp表中所有员工信息 
1.先创建一个Maven Project,Group Id:com.tedu; Artifact Id:CGB-MYBATIS-01; Packging:jar
2.在pom.xml里添加如下代码,用来配置各种环境,之后会在Maven Dependencies里显示
	<dependencies>
		<!-- junit单元测试 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
		</dependency>
		<!-- mysql驱动 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.32</version>
		</dependency>
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.8</version>
		</dependency>
		<!-- 整合log4j -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.6.4</version>
		</dependency>
	</dependencies>
3.在src/main/java里新建一个class类,命名为MyBatisTest01
4.新建xml,命名为mybatis-config.xml
  把unit08-mybatis中的mybatis-config[模板].xml里的内容粘贴在建好的xml文件里
	在里面添加入下代码:
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE configuration
	    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	    "http://mybatis.org/dtd/mybatis-3-config.dtd">
	<configuration>
		<!-- 配置文件不要求大家记住,但需要大家会修改 -->
		<!-- 1.配置开发环境 default等于哪个环境的id值就使用哪个环境 -->
			<environments default="develop">
				<environment id="develop">
			<!-- 指定事务管理方式,type="JDBC":将事务交给JDBC来管理,type="MANAGED":自己管理事务 -->
					<transactionManager type="JDBC" />
					<!-- dataSource(其实就是数据源,也就是连接池):指定连接数据库的基本信息 
					type:POOLED就是使用连连接池UNPOOLED就是不使用连接池 -->
					<dataSource type="POOLED">
						<property name="driver" value="com.mysql.jdbc.Driver" />
						<property name="url"
							value="jdbc:mysql:///yonghedb?characterEncoding=utf-8" />
						<property name="username" value="root" />
						<property name="password" value="root" />
					</dataSource>
				</environment>
			</environments>
			<!-- 2.导入MAPPER文件(SQL语句) resource指向MAPPER文件在类目录中的位置 -->
			<mappers>
				<mapper resource="EmpMapper.xml" />
			</mappers>
	</configuration>                                                
5.新建xml,命名为EmpMapper.xml
  把unit08-mybatis中的EmpMapper[模板].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">
	<mapper namespace="EmpMapper">
		<!-- select insert update delete -->
		<!-- 练习1:查询emp表中的所有员工信息 -->
		<select id="findAll01" resultType="com.tedu.pojo.Emp">
			select * from emp
		</select>
	</mapper>
6.新建一个类,命名为Emp,建在com.tedu.opjo包下,在里面添加如下代码
	package com.tedu.pojo;	
	public class Emp {
		private Integer id;
		private String name;
		private String job;
		private Double salary;

		// 提供Getting/Setting方法
		public Integer getId() {
			return id;
		}

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

		public String getName() {
			return name;
		}

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

		public String getJob() {
			return job;
		}

		public void setJob(String job) {
			this.job = job;
		}

		public Double getSalary() {
			return salary;
		}

		public void setSalary(Double salary) {
			this.salary = salary;
		}

		// 提供toString方法
		@Override
		public String toString() {
			return "Emp [id=" + id + ", name=" + name + ", job=" + job + ", salary=" + salary + "]";
		}
7.新建一个类,命名为MyBatisTest01,在里面添加如下代码:
	public class MyBatisTest01 {
	/* 练习01:查询yonghedb.emp表中所有员工信息 */
	@Test
	public void testFindAll01() throws Exception {
		// 1.读取mybatis的核心配置文件(mybatis-config.xml)
		InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
		// 2.获取SqlSessionFactory工厂对象
		SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in);
		// 3.获取SqlSession对象(true:自动提交事务,false[默认]:手动提交事务)
		SqlSession session = fac.openSession(true);
		// 4.执行SQL语句(EmpMapper.xml),返回处理后的结果,namespace+id--sql语句的定位标识
		List<Emp> list = session.selectList("EmpMapper.findAll01");
		// 5.输出结果到控制台
		for (Emp emp : list) {
			System.out.println(emp);
		}
8.新建一个类,用来添加数据

二、Mybatis入门案例,跟上面对应

--新增员工信息:赵云 保安 6000
1.在EmpMapper.xml下添加如下代码
	<!-- 练习2:新增员工信息:赵云 保安 6000 -->
	<insert id="insert02">
		insert into emp value(null,'赵云','保安',6000)
	</insert>
复制一份MyBatisTest01,名字改为MyBatisTest02,在里面把前三行代码放在before里,做如下修改:
	public class MyBatisTest02 {
	private SqlSession session = null;
	@Before /* 标记的方法会在@Test注标记的方法之前执行 */
	public void testBefore() throws IOException {
		// 1.读取mybatis的核心配置文件(mybatis-config.xml)
		InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
		// 2.获取SqlSessionFactory工厂对象
		SqlSessionFactory fac = new SqlSessionFactoryBuilder().build(in);
		// 3.获取SqlSession对象(true:自动提交事务,false[默认]:手动提交事务)
		session = fac.openSession(true);
	}
	/* 练习2:新增员工信息:赵云 保安 6000 */
	@Test
	public void testInsert02() throws Exception {
		int rows = session.insert("EmpMapper.insert02");
		System.out.println("Affected rows:" + rows);
		// session.commit;上面加了session = fac.openSession(true);就不用每次都自己手动提交了
	}
2.修改和删除跟添加的代码一模一样,同等原理
	只需要在EmpMapper.xml添加一个update方法,修改insert02改为update03即为修改
	练习3:修改员工信息:赵云 保镖 20000
	@Test
	public void testUpdate03() throws Exception {
		int rows = session.update("EmpMapper.update03");
		System.out.println("Affected rows:" + rows);
		// session.commit;上面加了session = fac.openSession(true);就不用每次都自己手动提交了
	}
3.只需要在EmpMapper.xml添加一个delete方法,修改insert02改为delete04即为删除
	练习4:删除赵云 
	@Test
	public void testDelete04() throws Exception {
		int rows = session.delete("EmpMapper.delete04");
		System.out.println("Affected rows:" + rows);
		// session.commit;上面加了session = fac.openSession(true);就不用每次都自己手动提交了
	}

三、Mybatis中的占位符

1.概念
自己:如果#占位符只有一个,括号里的名称可以随便写,但是不能空着,如果#占位符有多个,名称一定要和map中的key一致
老师:如果在SQL语句中只有一个#{}占位符,{}中名称没有要求,但不能是空的;
	如果在SQL语句中的#{}占位符,不止一个,参数值需要通过Map或者P0J0对象进行封装;
	如果通过Map集合来封装SQL参数值,#{}占位符中的名称要和Map中的key保持一致!
	因为在mybatis底层是通过#{}占位符中的名称,作为key到map中获取对应的value;如果通过P0J0对象来封装SQL参数值
	#{}占位符中的名要在PO10对象中有对应的getXx方法,
	例如∶#{job}占位符中的名称为job,那么就意味着,在Emp中必然有getJob()方法或者有job变量
	如果两者都有,会优先通过getXXx方法来获取PO30对象中存储的属性值
	pojo:简单java对象,专指用于封装数据的对象
2.查询emp表中指定id的员工信息
	@Test
	public void testFindById05() throws IOException{
		int id=5;
		Emp emp=session.selectOne("EmpMapper.findById05",id);
		System.out.println(emp);
	}
在EmpMapper.xml添加如下代码:
	<!-- 练习5:查询emp表中指定id的员工信息 -->
	<select id="findById05" resultType="com.tedu.pojo.Emp">
		<!-- #{},花括号里面的值时占位符的名称,如果#占位符只有一个,括号里的名称可以随便写,但是不能空着 -->
		select * from emp where id=#{id};
	</select>
3.新增员工信息:张飞 Java开发工程师15000
	@Test
	public void testInsert06() throws IOException {
		// 将要传输的参数封装到map集合中
		Map map = new HashMap();
		map.put("name", "张飞");
		map.put("job", "Java开发工程师");
		map.put("salary", 15000);
		// 也可以将要传输的参数封装到Emp对象中
		int rows = session.insert("EmpMapper.insert06", map);
		System.out.println("Affected rows:" + rows);
	}
在EmpMapper.xml添加如下代码:
	<!-- 练习6:新增员工信息:张飞 Java开发工程师15000 名称一定要和map中的key一致-->
	<insert id="insert06">
		insert into emp value( null,#{name},#{job},#{salary})
	</insert>
4.修改员工信息:于影 CEO 100000000000000
	@Test
	public void testUpdate07() throws IOException {
		// 可以将SQL参数值封装到POJO对象中,再将POJO对象传递给SQL
		Emp emp = new Emp();
		emp.setName("于影");
		emp.setJob("CEO");
		emp.setSalary(100000000000000D);
		int rows = session.update("EmpMapper.update07",emp);
		System.out.println("Affected rows:" + rows);
	}
在EmpMapper.xml添加如下代码:
	<!-- 练习7:修改员工信息:于影 CEO 100000000000000 -->
	<update id="update07">
		update emp set job=#{job},salary=#{salary} where name=#{name}
	</update>
5.删除emp表中指定id的员工信息

四、几个可以优化的地方

1.加入log4j日志框架(新建一个log4j.properties文件,在讲义中可以优化的地方下方粘贴代码在log4j.properties文件里)
	导入log4j的jar包,在源码根目录下提供一个 log4j.properties 文件,并提供配置信息,代码如下:
		# Global logging configuration
		log4j.rootLogger=DEBUG, stdout
		# Console output...
		log4j.appender.stdout=org.apache.log4j.ConsoleAppender
		log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
		log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2、${}占位符
	#{}占位符∶相当于JDBC中的问号(?)占位符,它是为SQL语句中的参数值进行占位,例如下方代码:
		insert into emp values(null,#{name},#{job},#(salary));
		update emp set job=#(job},salary=#(salary} where name=#{name}
		delete from emp where name=#{name}
		delete from emp where id=#{id)
		select* from emp where name=#{name} and job=#{job}
 	${}占位符:是为SQL语句中的某一个SQL片段进行占位,将参数传递过来时,是直接将参数拼接在${}占位符所在的位置
 	        因为是直接拼接,所以可能会引发SQL注入攻击,因此不推荐大量使用
 	如果SQL语句中只有一个#{}占位符,参数可以不用封装,直接传递即可!
	但如果SQL语句中哪怕只有一个${}占位符,参数也必须得先封装到Map或者P0J0对象中,再把Map或者POJ0对象传递过去
3.动态指定要显示的列
	练习8:动态指定要显示的列
	@Test
	public void testFindAll08() throws Exception{
		String colName = "*";
		Map map = new HashMap();
		map.put("colName", colName);
		List<Emp> list = session.selectList("EmpMapper.findAll08");
		for (Emp emp : list) {
			System.out.println(emp);
		}
	}
 	在EmpMapper.xml文件里添加如下代码
 		<!-- 练习8:动态指定要显示的列 -->
		<select id="findAll08" resultType="com.tedu.pojo.Emp">
			select ${colName} from emp
		</select>
4.根据name模糊查询emp表,查询姓刘的,用${}占位符
	@Test
	public void testFindAll09() throws Exception {
		Map map = new HashMap();
		map.put("name","刘");
		List<Emp> list = session.selectList("EmpMapper.findAll09", map);
		for (Emp emp : list) {
			System.out.println(emp);
			}
		}
	在EmpMapper.xml文件里添加如下代码
	<!-- 练习9:根据name模糊查询emp表,查询姓刘的,用${}占位符 -->
		<select id="findAll09" resultType="com.tedu.pojo.Emp">
			select * from emp where name like '%${name}%'
		</select>
5.根据name模糊查询emp表,查询姓刘的,用#{}占位符
	@Test 
	public void testFindAll09() throws Exception {
		Map map = new HashMap();
		map.put("name","%刘%");
		List<Emp> list = session.selectList("EmpMapper.findAll09", map);
		for (Emp emp : list) {
			System.out.println(emp);
			}
		}
	在EmpMapper.xml文件里添加如下代码
	<!-- 练习10:根据name模糊查询emp表,查询姓刘的,用${}占位符 -->
		<select id="findAll10" resultType="com.tedu.pojo.Emp">
			select * from emp where name like #{name}
		</select>
PreparedStatement对象:
	1)先将SQL骨架发送给数据库服务器进行编译并确定下来(骨架一旦确定,就无法更改)
	2)再将SQL中的参数传递给服务器(此时如果参数中再包含关键字或者SQL特殊字符串,也不能影响骨架,只会被当成普通的文本来处理!)

五、动态SQL标签

1.根据薪资查询员工信息
	>的转义是&gt; <号的转义是&lt
	练习11:根据薪资查询员工信息
		@Test
		public void testFindBySalary11() {
			Map map = new HashMap();
			map.put("minSal", 3000);
			map.put("maxSal", 4000);
			List<Emp> list = session.selectList("EmpMapper.findBySalary11", map);
			for (Emp emp : list) {
				System.out.println(emp);
			}
		}
	在EmpMapper.xml文件里添加如下代码:
		<!-- 练习11:根据薪资查询员工信息 >的转义是&gt; <号的转义是&lt 或可以把特殊符号放在<![CDATA[  ]]>里面 -->
		<select id="findBySalary11" resultType="com.tedu.pojo.Emp">
			select * from emp
		<!-- 1=1加在where后面什么作用都没有,因为跟表没有任何关系,和不加where一个效果 -->
			where 1=1
			<if test="minSal != null">
				and salary >= #{minSal}
			</if>
			<if test="maxSal != null">
				and salary &lt;= #{maxSal}
			</if>
		</select>
2.根据薪资查询员工信息(where标签)   
	跟练习11一样的结果,就是把EmpMapper文件中的select标签内容中的where1=1换成了where标签
	id改为findBySalary12,代码如下:
	练习12:根据薪资查询员工信息(where标签)
	<select id="findBySalary12" resultType="com.tedu.pojo.Emp">
		select * from emp
		<where>
			<if test="minSal != null">
				and salary >= #{minSal}
			</if>
			<if test="maxSal != null">
				and salary &lt;= #{maxSal}
			</if>
		</where>
	</select>
3.根据员工的id批量删除员工信息(13省略,省略的是练习8:删除emp表中指定id的员工信息)
	/* 练习14:根据员工的id批量删除员工信息 */
	@Test
	public void testFindBySalary14() {
		Integer[] ids = { 4 };
		int rows = session.delete("EmpMapper.deleteByIds14", ids);
		System.out.println("Affected rows:" + rows);
	}
  在EmpMapper.xml文件里添加如下代码
  	<delete id="deleteByIds14">
		delete from emp where id in
		<foreach collection="array" open="(" item="id" separator=","
			close=")">#{id}</foreach>
	</delete>
4.foreach标签:
	(1)如果传的参数仅仅是一个数组或者List集合,collection指定的值则为array或list
	   如果传的参数有多个,用map集合进行封装,collection指定的值则为数组/集合在map中的key
	(2)open:指定所生成字符串的起始符号
	(3)close:指定所生成字符串的结束符号
	(4)item:指定占位符中的名称
	(5)separator:指定遍历的元素之间的间隔符
5.根据员工的id批量更新员工薪资
	/* 练习15: 根据员工的id批量更新员工信,将id为 6,14,15,19的员工的薪资在原有基础上增加1000 */
		@Test
		public void testUpdateByIds() {
			Integer[] ids = { 6, 14, 15, 19 };
			Map map = new HashMap();
			map.put("count", 10000);
			map.put("idsArr", ids);
			int rows = session.update("EmpMapper.updateByIds15", map);
			System.out.println("Affected rows:" + rows);
		}
	在EmpMapper.xml文件里添加如下代码
		<!-- 练习15:将id为 6,14,15,19的员工的薪资在原有基础上增加1000 -->
		<update id="updateByIds15">
		update emp set salary = salary+1000 where id in (6,14,15,19)
			update emp set salary = salary + #{count} where id in
			<foreach collection="idsArr" open="(" item = "sal" separator="," close=")">
				#{sal}
			</foreach>
		</update>

六、Mapper接口开发

mapper接口开发需满足一下四个原则
1.写一个接口,要求接口的全类名(包名+接口名)要等于mapper文件的namespace值
	namespace = 接口的全类名
2.mapper文件中要执行的SQL,在接口中得到对应的接口方法,而且SQL标签的ID值要等于方法名
	SQL语句的ID值 = 方法名
3.如果是查询SQL,resultType属性中指定的类型,要和接口方法的返回值类型保持一致
 	(如果接口方法返回的是List集合,resultType属性只需要指定集合中的泛型)
4.SQL标签的参数类型(可以省略)要和接口方法的参数类型保持一致

七、Mapper接口开发的练习

1.把CGB-MYBATIS-01复制一份,改为CGB-MYBATIS-01,复制com.tedu的MyBatisTest02复制一份,改为MyBatisTest03,	  删除01,02,MyBatisTest03类里面只留before和private SqlSession session = null;
2.新建一个接口,命名为EmpMapper,包名命名为com.tedu.dao,建好之后右键EmpMapper选择copy Qualified name(全类名)
3.打开EmpMapper.xml文件找到mapper的namespace,把接口全类名粘贴进去,必须和全类名一致
4.在EmpMapper接口里添加一个方法,方法名字要和id值一致,代码如下
	public interface EmpMapper {
		// 查询所有员工的信息
		public List<Emp> findAll01();
	}
5.在MyBatisTest03类中添加一个方法,代码如下
	/* Mapper接口开发01:查询emp表所有信息 */
		@Test
		public void testFindAll01() {
			/* (1)获取EmpMapper接口的实现类实例
			 * 框架底层可以根据GetMappper方法接收的EmpMapper接口的字节码对象,提供接口的实现类
			 * 并根据接口的实现类,创建实现类的实例,同时也可以获取接口的全类名(=namespace)
			*/
			括号里传接口的字节码对象,也就是class对象,接口名.class
			     把字节码对象传给GetMappper方法,并实现接口
			EmpMapper mapper = session.getMapper(EmpMapper.class);
			/* (2)调用findAll01方法
			 *
			 *
			*/
			List<Emp> list = mapper.findAll01();
			for (Emp emp : list) {
				System.out.println(emp);
			}
		}

八、MyBatis注解开发

xml修改方便,编写起来很麻烦,对语法要求很严格,注解开发修改不方便,编写起来方便
1.在接口上方写一个select注解代替查询
	@Select("select * from emp")
2.在接口上方写一个insert注解代替添加
	@insert("insert into emp value( null,#{name},#{job},#{salary})")
3.在接口上方写一个update注解代替修改
	@Update("update emp set name=#{name},job=#{job},salary=#{salary} where id=#{id}")
4.在接口上方写一delete个注解代替删除
	@Delete("delete from emp where id=#{id}")
SQL语句加判断很麻烦,可读性差
@Select("<script>select * from emp where 1=1 <if test=\"minSal!=null\"> 
          and price > minSal </if><script>")

九、内容补充

1.POJO(Plain Old Java Object/Plain Ordinary Java Object)
	简单Java对象:是指专门用于封装数据的数据的对象
2.Emp中的属性为什么不能是基本类型
	public class Emp{
		private Integer id;
		private String name;
		private String job;
		private Double salary;//默认值为null;
		private double score; //默认值为0.0;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值