Java复习之路(第二十六天 mybatis )

Java基础(框架)

什么是mybatis:

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

总之,Mybatis对JDBC访问数据库的过程进行了封装,简化了JDBC代码,解决JDBC将结果集封装为Java对象的麻烦。

为什么要使用Mybatis

思考:在开始之前,思考下如何通过JDBC查询Emp表中的所有记录,并封装到一个List<Emp>集合中返回。(演示:准备数据、导包、导入JDBC程序)

1.在使用传统的方式JDBC访问数据库

(1)使用JDBC访问数据库有大量重复代码(比如注册驱动、获取连接、获取传输器、释放资源等);

(2)JDBC自身没有连接池,会频繁的创建连接和关闭连接,效率低;

(3)SQL是写死在程序中,一旦修改SQL,需要对类重新编译;

(4)对查询SQL执行后返回的ResultSet对象,需要手动处理,有时会特别麻烦;

使用Mybatis框架访问数据库:

(1)Mybatis对JDBC对了封装,可以简化JDBC代码;

(2)Mybatis自身支持连接池(也可以配置其他的连接池),因此可以提高程序的效率;

(3)Mybatis是将SQL配置在mapper文件中,修改SQL只是修改配置文件,类不需要重新编译。

(4)对查询SQL执行后返回的ResultSet对象,Mybatis会帮我们处理,转换成Java对象。

总之,JDBC中所有的问题(代码繁琐、有太多重复代码、需要操作太多对象、释放资源、对结果的处理太麻烦等),在Mybatis框架中几乎都得到了解决!!

mybatis的入门案例:

首先准备数据库:创建yonghedb数据库和emp表格,在向其中插入一定的语句

-- 1、创建数据库 yonghedb 数据库
create database if not exists yonghedb charset utf8;
use yonghedb; -- 选择yonghedb数据库
-- 2、删除emp表(如果存在)
drop table if exists emp;
-- 3、在 yonghedb 库中创建 emp 表
create table emp(
	id int primary key auto_increment,
	name varchar(50),
	job varchar(50),
	salary double
);
-- 4、往 emp 表中, 插入若干条记录
insert into emp values(null, '王海涛', '程序员', 3300);
insert into emp values(null, '齐雷', '程序员', 2800);
insert into emp values(null, '刘沛霞', '程序员鼓励师', 2700);
insert into emp values(null, '陈子枢', '部门总监', 4200);
insert into emp values(null, '刘昱江', '程序员', 3000);
insert into emp values(null, '董长春', '程序员', 3500);
insert into emp values(null, '苍老师', '程序员', 3700);
insert into emp values(null, '韩少云', 'CEO', 5000);

创建工程,导入所需要的jar包,创建测试类:

创建maven工程:

导入Junit mysql mybatis等开发包

在pox.xml文件中引入相关的依赖包就可以

<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>

创建com.tedu.mybatis.Testmybatis测试类,并提供findAll方法(查询emp表格中所有的员工信息),开发步骤如下

/** 练习1(快速入门):  查询emp表中的所有员工, 返回一个List<Emp>集合
 * @throws IOException */
@Test
public void findAll() throws IOException {
	//1.读取mybatis的核心配置文件(mybatis-config.xml)
	
	//2.通过配置信息获取一个SqlSessionFactory工厂对象
	
	//3.通过工厂获取一个SqlSession对象
	
	//4.通过namespace+id找到要执行的sql语句并执行sql语句
	
	//5.输出结果
	
}

添加mybatis-config.xml文件:

1.在src/main/resources目录下,创建mybatis-config.xml文件 (MyBatis的核心配置文件)

2.mybatis-config.xml文件配置如下:

mybatis-config.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">
    
<!-- MyBatis的全局配置文件 -->
<configuration >
	
</configuration>

详细的配置情况:

<?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">
    
<!-- MyBatis的全局配置文件 -->
<configuration >
	<!--1.配置开发环境,其中可以配置多个environment标签,每一个
		environment是一个独立的开发环境 -->
		<!--代表的含义就是实用的是当前的某一个的配置环境  -->
	<environments default="develop">
		<environment id="develop">
			<!--1.配置事务的管理方式
					JDBC:将事务交给JDBC管理(推荐)
					MANAGED:自己管理事务 -->
			<transactionManager type="JDBC"></transactionManager>
			<!--2.配置数据源 (连接池)
				POOLED:使用连接池
				UNPOOLED:不适用连接池
				JNDI:已过时
				-->
			<dataSource type="POOLED">
				<!--配置连接数据库的基本的信息  -->
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
				<property name="username" value="root"/>
				<property name="password" value="123456"/>
			</dataSource>
		</environment>
	</environments>
	<!--导入mapper.xml文件的,其中包含了我们要执行的事情了语句  -->
<mappers>
<!--直接去文件的源码的目录下去寻找,因为在同一个目录下,所以直接写文件的名称就可以 -->
	<mapper resource="EmpMapper.xml"/>
</mappers>	
</configuration>

添加并编写Emp实体类

注意:在当前实例中,Emp类中的属性和数据库表的字段名称必须一致,否则将会无法将结果集封装到Java对象中。

在src/main/java目录下创建com.tedu.pojo.Emp类并实现Emp类:提供私有属性以及对应的getter方法、setter方法,并重写toString方法

package com.tedu.pojo;
/**
 * 实体类,用于封装Emp表中的一条用户信息
 */
public class Emp {
	//1.声明实体类中的属性
	private Integer id;
	private String name;
	private String job;
	private Double salary;
	
	//2.提供对应的getter和setter方法
	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;
	}
	
	//3.重写toString方法
	@Override
	public String toString() {
		return "Emp [id=" + id + ", name=" + name + ", job=" + job + ", salary=" + salary + "]";
	}
}

添加EmpMapper.xml文件

1、在src/main/resources目录下,创建EmpMapper.xml文件 (实体类的映射文件)

2、EmpMapper.xml文件配置如下:

EmpMapper文件头信息配置如下:

<?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一般指定为当前文件的所在包路径+文件名(将来是接口名)
	在程序中通过[ namespace + id ]定位到执行哪一条SQL语句
 -->
<mapper namespace="">
	
	
</mapper>
<?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一般指定为当前文件的所在包路径+文件名(将来是接口名)
	在程序中通过[ namespace + id ]定位到执行哪一条SQL语句
	com.tedu.dao.EmpMapper.java(接口)
 -->
<mapper namespace="EmpMapper">
<!--就是来书写sql语句的文件-->
	<!--
			select、update、delete、insert
	  -->
	  <!-- 练习一:查询emp表中的所有员工的信息
	  		id值不可以重复,必须唯一  resultType方法是用于将查询的结果封装到那个类型中
	  -->
	  <select id="findAll" resultType="com.tedu.pojo.Emp">
	  	select * from emp;
	  </select>
	  <!--练习二:往emp的表格中插入一条员工的信息
	    张三  高级开发工程师  25000
	   -->
	   
	   <!--添加数据的时候,返回的值是不用封装的  -->
	   <update id="insert">
	   		insert into emp values(null,'张三','高级开发工程师',25000)
	   </update>
	   
	   <!--查询emp表中name为王海涛的员工的信息  -->
	   <select id="findById" resultType="com.tedu.pojo.Emp">
	   		select * from emp where name="王海涛"
	   </select>
	  
</mapper>

实现测试类,并发类

实现的findAll方法,代码如下

package com.tedu.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

//在导包的时候一定要注意包的名称2
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.tedu.pojo.Emp;
/*
 * Mybatis的快速入门的程序
 */
public class TestMybatis {
	/*
	 * 练习一:查询员工表中的所有的员工的信息
	 *将所有的员工信息封装到List<Emp>集合中
	 */
	@Test 
	public void findAll() throws IOException {
		//1.读取mybatis的核心配置文件(mybatis-config)
		//可能会出现路径找不到的异常,所以在此处有一个异常需要处理
		InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
		//2.通过配置获取一个sqlsessionFactory工厂
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
		//3.通过工厂获取一个sqlsession对象
		SqlSession session = factory.openSession();
		//4.执行sql语句(namespace+id),返回结果
		//里面的参数就是sql路径的地址
		List<Emp> list = session.selectList("EmpMapper.findAll");
		//list<Emp> empList=......
		//5.进行输出结果
		for (Emp emp : list) {
			System.out.println(emp);
		}
	}
}

执行findAll方法,输出的结果为

Emp [id=1, name=王海涛, job=程序员, salary=3300.0]
Emp [id=2, name=齐雷, job=程序员, salary=2800.0]
Emp [id=3, name=刘沛霞, job=程序员鼓励师, salary=2700.0]
Emp [id=4, name=陈子枢, job=部门总监, salary=4200.0]
Emp [id=5, name=刘昱江, job=程序员, salary=3000.0]
Emp [id=6, name=董长春, job=程序员, salary=3500.0]
Emp [id=7, name=苍老师, job=程序员, salary=3700.0]
Emp [id=8, name=韩少云, job=CEO, salary=5000.0]

MyBatis入门细节:

mybatis-config.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">
    
<!-- MyBatis的全局配置文件 -->
<configuration >
	<!-- 配置环境,可配置多个环境(比如:develop开发、test测试) -->
	<environments default="develop">
		<environment id="develop">
			
			<!-- 配置事务管理方式:JDBC/MANAGED
			JDBC:将事务交给JDBC管理(推荐)
			MANAGED:自己管理事务
			  -->
			<transactionManager type="JDBC"></transactionManager>
			
			<!-- 配置数据源,即连接池 JNDI/POOLED/UNPOOLED
				JNDI:已过时
				POOLED:使用连接池(推荐)
				UNPOOLED:不使用连接池
			 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 引入Mapper配置文件,可以配置多个 -->
	<mappers>
		<mapper resource="EmpMapper.xml"/>
	</mappers>

</configuration>

configuration是根标签,当前文件中所有的配置都在该标签内,注意其中配置的关键点:

默认的环境 ID(比如:default="develop")。
每个 environment 元素定义的环境 ID(比如:id="develop")。
事务管理器的配置(比如:type="JDBC")。
数据源的配置(比如:type="POOLED")。

(1)environments标签:该标签内部可以配置多个environment,即多种环境,每种环境可以做不同配置或连接不同数据库。例如,开发、测试、生产环境可能需要不同的配置,连接的数据库可能也不相同,因此我们可以配置三个environment,分别对应上面三种不同的环境。

但是要记住,environment可以配置多个,但是最终要使用的只能是其中一个!

(2)environment标签:内部可以配置多种配置信息,下面介绍事务管理配置和数据源配置。

(3)transactionManage标签:事务管理配置,mybatis中有两种事务管理方式,也就是 type="[JDBC|MANAGED]。

JDBC:这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。推荐使用。

MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。需要自己手动添加并管理。不推荐使用。

(4)dataSource标签:数据源,也就是连接池配置。这里type指定数据源类型,有三种内建的类型:JNDI、POOLED、UNPOOLED

JNDI:已过时,不推荐使用!

POOLED:使用连接池,mybatis会创建连接池,并从连接池中获取连接访问数据库,在操作完成后,将会把连接返回连接池。

UNPOOLED:不使用连接池,该方式适用于只有小规模数量并发用户的简单应用程序上。

(5)mappers标签:用于导入mapper文件的位置,其中可以配置多个mapper,即可以导入多个mapper文件。

EmpMapper.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一般指定为当前文件的所在包路径+文件名
	将来在程序中通过[ namespace + id ]定位到执行哪一条SQL语句
 -->
<mapper namespace="EmpMapper">
	<!-- 通过select、insert、update、delete标签声明要执行的SQL -->
	<select id="findAll" resultType="com.tedu.pojo.Emp">
		select * from emp
	</select>
	<!-- 
	resultType:返回值类型,简单类型(例如:Integer,String,Emp等)
		如果返回集合(List<Emp>),只需配置集合中的元素类型即可!
	resultMap:复杂对象结构(例如多表关联查询等),后面用到再讲解
	 -->
</mapper>

(1)第1行是xml的文档声明,用于声明xml的版本和编码

(2)第2、3、4行,引入了xml约束文档,当前xml文档将会按照mybatis-3-mapper.dtd文件所要求的规则进行书写。

(3)Mapper标签:根标签,其中namespace(名称空间,也叫命名空间),要求不能重复。其实就是一个名称,一般我们指定为"包名+文件名"。

(4)select标签:用于指定将来要执行的各种SQL语句。标签上可以声明属性,下面介绍常用的属性:idresultTyperesultMap

id属性:要求值不能重复。将来在执行SQL时,可以通过namespace + id找到指定SQL并执行。

resultType属性:从这条SQL语句中返回所期望类型的类的完全限定名称(包名+类名)。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。

简而言之,resultType控制查询SQL执行后返回值的类型或集合中的泛型,例如查询emp表中的单条记录,返回值是一个Emp对象,因此,resultType="com.tedu.pojo.Emp";

如果查询emp表中的多条记录,返回值是一个List<Emp>,此时resultType的值应该集合中的泛型,因此resultType="com.tedu.pojo.Emp";

resultMap属性:复杂对象结构(例如多表关联查询等)。 使用 resultType 或 resultMap,但不能同时使用。

Mybatis增删改查

新增员工:

1、编辑EmpMapper.xml文件, 添加新增员工对应的sql.

<!-- 练习2: 新增员工信息: 刘德华 歌手 888
	增删改的标签上不用指定resultType, 因为返回值都是int类型
 -->
<update id="insert" >
	insert into emp value(null, '刘德华', '歌手', 888)
</update>

2、编写TestMybatis类,添加testInsert方法,实现新增员工操作。

/** 练习2: 新增员工信息: 刘德华 歌手 888 */
@Test
public void testInsert() { 
	//执行sql语句, 返回执行结果
	int rows = session.update("EmpMapper.insert");
	//提交事务
	session.commit();
	System.out.println("影响的行数: "+rows);
}

修改员工

1、编辑EmpMapper.xml文件, 添加新增员工对应的sql.

<!-- 练习3:修改员工信息 -->
<update id="update">
	update emp set job='歌手&演员', salary=8888 where name='刘德华'
</update>

2、编写TestMybatis类,添加testUpdate方法,实现修改员工信息。

/** 练习3: 修改员工信息, 将刘德华的job改为'歌手&演员' 
 * 		salary改为88888 */
@Test
public void testUpdate() { }
	//执行sql语句, 返回执行结果
	int rows = session.update("EmpMapper.update");
	//提交事务
	session.commit();
	System.out.println("影响行数:"+rows);
}

删除员工:

1、编辑EmpMapper.xml文件, 添加新增员工对应的sql.

<!-- 练习4: 删除name为'刘德华'的记录 -->
<update id="delete">
	delete from emp where name='刘德华'
</update>

2、编写TestMybatis类,添加testDelete方法,实现删除员工。

/** 练习4: 删除name为'刘德华'的记录 */
@Test
public void testDelete() {
	//执行sql语句, 返回执行结果
	int rows = session.update("EmpMapper.delete");
	//提交事务
	session.commit();
	System.out.println("影响行数:"+rows);
}

#{}占位符和${}占位符

在上面的增删改查练习中,当SQL语句中包含的参数值是传递过来的,在SQL语句中我们会通过 #{} 占位符进行占位,在SQL语句真正执行时,再将传递过来的值替换SQL语句中的占位符。

其实,#{} 就是JDBC中的问号(?)占位符,因此为了安全考虑,在执行时会对传递过来的值进行转译处理。

例如:查询指定name的员工信息,SQL语句为:

select * from emp where name=#{name}

其实就等价于JDBC中: select * from emp where name=?,如果传过来的参数值为:王海涛,那么最终执行的SQL语句为:

select * from emp where name='王海涛'

那么如果我们在传递的时候不是一个参数值,而是一个SQL片段呢?例如在查询时,我们想动态的传递查询的列:

select 查询的列?? from emp

案例:在更新数据库的数据的时候,两种方法

两种方法通用的配置文件:

	 	<update id="updateById">
	 	<!--前面的name是封装的Emp表格中的name属性
	 		后面的{}里面的name是在emp表格中的name的属性名称
	 		
	 	占位符中的变量名称和Emp类中的属性名称最好保持一致否则可能会导致传过来的值获取不到,无法替换
	 	  -->
	 		update  emp  set  name=#{name}, job=#{job}, salary=#{salary} where id=#{id}
	 	</update>

1.利用占位符号的方法进行更改数据

	public void testUpdateById() {
		//执行SQL语句
		//将数据封装为一个参数
		Emp emp=new Emp();
		//给要修改的对象进行赋值
                //如果sql语句中有占位符,在执行sql语句时,要将数据分装到对象或者map集合中进行传递过去,需要注意的是,占位符中的变量名称最好和对象中的属性名称以及map中的key保持一致
		emp.setId(1);
		emp.setName("大表哥");
		emp.setJob("Java开发工程师");
		emp.setSalary(2000);
		int rows = session.update("EmpMapper.updateById",emp);
		session.commit();
		System.out.println("影响的行数"+rows);
	}

2.利用Map集合的形式进行更改数据

	public void testUpdateById() {
		//执行SQL语句
		//更新数据的两种方法,1.将数据进行封装  2.利用Map集合进行传送数据
		//利用Map集合遍历的方法进行查询数据
		Map map=new HashMap();
		//前面的参数是和占位符号一致的,就是未知的参数
		//后面就是要修改的值
		map.put("id", 3);
		map.put("name", "马化腾");
		map.put("job", "董事长");
		map.put("salary", 3000);
		//直接将map的集合进行传送过去,放在第二个参数的位置
		int rows = session.update("EmpMapper.updateById",map);
		//提交事务
		session.commit();
		System.out.println("影响的行数"+rows);
	}

练习:进行数据库中数据的添加

	//练习七:添加:往emp表中添加一条员工的信息林青霞 演员 2200  
	@Test
	public void testIntert2() {
	//将SQL的参数值封装到对象中,或者是封装到Map的集合中
	Emp emp=new Emp();
	emp.setJob("演员");
	emp.setName("林青霞");
	emp.setSalary(20000);
	//执行sql语句,返回执行的结果
	int rows = session.update("EmpMapper.insert2",emp);
	//提交事务
	session.commit();
	System.out.println("影响的行数"+rows);
	}

进行数据添加的配置文件

	 	<update id="insert2">
	 		insert into emp values(null,#{job},#{name},#{salary});
	 	</update>

查询单个数据的方法:

	@Test
	public  void testFindById2() {
		//执行sql语句,返回执行的结果
		Object emp = session.selectOne("EmpMapper.findById2", 3);
		System.out.println(emp);
	}

配置的文件

	 	<select id="findById2" resultType="com.tedu.pojo.Emp">
	 		select * from emp where id=#{id};
	 	</select>

进行选择行的进行动态的进行筛选数据:

	@Test
	public void testFindAll2() {
		//将sql参数封装到Map的集合中
		Map map=new HashMap();
		map.put("cols", "job,name");
		//执行sql语句
		List<Emp> list = session.selectList("EmpMapper.findAll2",map);
		for (Emp emp : list) {
			System.out.println(emp);
		}
	}

 MapMapper.xml文件的配置:

	 	<select id="findAll2" resultType="com.tedu.pojo.Emp">
	 		select ${cols} from emp ;
	 	</select>

进行模糊查询操作:

	public void testFindByName() {
		//用#占位符进行代替的,进行解析的时候加上"",
		//用$占位符号进行占位的话,解析之后得到的就是占位符里面的内容
		//$占位符起到的就是拼接的作用
		Map map=new HashMap();
		map.put("name", "马");
		//进行执行sql语句
		List<Emp> list = session.selectList("EmpMapper.FindByName",map);
		for (Emp emp : list) {
			System.out.println(emp);
		}
	}

 模糊查询的配置文件:

	 	<select id="FindByName" resultType="com.tedu.pojo.Emp">
	 		select * from emp where name like '%${name}%';
	 	</select>

在框架中sql语句执行的流程图:

1.根据执行sql语句中的方法中传入的namespace+id的值,到Map中找到要执行的sql语句,并执行sql语句

2.sql执行后,返回一条记录,将一条记录封装到Java的对象中(根据resultType指定的类型,创建一个Java的对象,将当前的这条记录封装到Java的对象中)

根据数据表中的列名

id列--->emp.setid(1);

name列--->emp.setname("大表哥")

3.在将表中的数据封装到Java的对象中的时候,要保证列表中的列名和Java对象中的属性一致,数据才可以封装进行

底层的原理:

封装的对象,就是将表格中的属性进行封装个成为set+属性名称,然后依照这个名称到封装的对象中进行寻找方法,若可以找到,进行赋值,找不导相对应的方法,就会返回null值

在将表中的数据封装到Java的对象时,要保证表中的列名和Java对象中的属性一致,数据就可以封装进行。

动态的SQL

1.where 和 if的语句:

(1)mybatis中的if元素用于对某一字段进行判断,比如根据判断传过来的参数是否为空,从而决定是否执行包含在其中的SQL片段。

(2)where元素则用于对包含在其中的SQL语句进行检索,需要时会剔除多余的连接词(比如and或者or),并且在需要时可以添加where关键词,进行筛选的条件

动态的实现数据的查询功能:

<!-- 练习12.1: 根据薪资查询员工信息
 * 练习12: 根据薪资查询员工信息
 * 如果参数有 minSal、maxSal, 则
 * ... where salary > minSal and salary < maxSal
 * 如果参数中只有minSal, 则
 * ... where salary > minSal 
 * 如果参数中只有maxSal, 则
 * ... where salary < maxSal
 * 如果没有参数, 则不执行where子句, 默认查询所有员工 -->
<select id="findAllBySal"  
			 resultType="com.tedu.pojo.Emp">
	select * from emp
	where	1=1
		<if test="minSal != null">
			and salary>#{minSal}
		</if>
		<if test="maxSal != null">
			and salary <![CDATA[ < ]]> #{maxSal} 
		</if>
</select>

<!-- 练习12.2: 根据薪资查询员工信息 -->
<select id="findAllBySal2"  
			 resultType="com.tedu.pojo.Emp">
	select * from emp
	<where>
		<if test="minSal != null">
			and salary>#{minSal}
		</if>
		<if test="maxSal != null">
			and salary <![CDATA[ < ]]> #{maxSal} 
		</if>
	</where> 
</select>

Java语句的书写:

/*----------- 动态SQL -----------
 * if标签: 判断若为true, 则执行if中的sql片段
 * where标签: 生成where关键字, 对其中多余的连接词
 * 		进行处理
 * set标签: 生产set关键字, 对其中多余的连接符进行处理
 * 		set 列1=值1, 列2=值2
 * foreach标签: 进行循环遍历, 比如实现批量删除
 */

/**
 * 练习12: 根据薪资查询员工信息
 * 如果参数有 minSal、maxSal, 则
 * ... where salary > minSal and salary < maxSal
 * 如果参数中只有minSal, 则
 * ... where salary > minSal 
 * 如果参数中只有maxSal, 则
 * ... where salary < maxSal
 * 如果没有参数, 则不执行where子句, 默认查询所有员工  */
@Test
public void testFindAllBySal() {
	//封装参数到map集合中
	Map map = new HashMap();
	map.put("minSal", 3000);
	map.put("maxSal", 5000.0);
	List<Emp> list = session.selectList(
				"EmpMapper.findAllBySal2", map);
	for (Emp emp : list) {
		System.out.println( emp );
	}
}

Set关键字:

mybatis中的set元素用于对包含在其中的SQL语句进行检索,在需要时可以剔除其中多余的连接符(比如逗号),并且在需要时可以添加set关键词

在没有关键字代替的时候:配置文件

	 	<!-- 修改员工的信息  -->
	 	<update id="updateById3">
	 		update emp set
	 		<if test="name !=null">
	 			name=#{name},
	 		</if>
	 		<if test="job !=null">
	 			job=#{job},
	 		</if>
	 		<if test="salary">
	 			salary=#{salary}
	 		</if>
	 		where id=#{id}
	 	</update>

利用se关键字进行改进的方法:就是set用关键字set标签进行替换

	 	<update id="updateById2">
	 		update emp
	 		<set>
		 		<if test="name !=null">
		 			name=#{name},
		 		</if>
		 		<if test="job !=null">
		 			job=#{job},
		 		</if>
		 		<if test="salary!=null">
		 			salary=#{salary}
		 		</if>
	 		</set>
	 		where id=#{id}
	 	</update>

在Java语句中

	public void testUpdateById3() {
		Emp emp =new Emp();
		emp.setId(4);
		emp.setName("刘宝宝");
		emp.setJob("程序员");
		emp.setSalary(12000.0);
		//执行sql语句
		int rows = session.update("EmpMapper.updateById2", emp);
		//进行提交事务
		session.commit();
		System.out.println("影响的行数是"+rows);
	}

删除多组数据的xml文件的配置:

	 	</update>
	 	<update id="delateByIds">
	 		delete from emp where id in
	 		<foreach collection="array" open="(" item="id"  
	 														separator="," close=")" >
	 			#{id}
	 		</foreach>
	 	</update>

删除多组数据的Java语句:

	public void testDeleteById() {
		//准备删除员工的id
		Integer [] ids= {1,2,3,4};
		//执行sql语句
		int rows = session.update("EmpMapper.delateByIds",ids);
		System.out.println("影响的行数"+rows);
	}

Mapper接口文件的开发(TestMybatis5项目)

Mapper接口案例的流程和运行的原理理解

Mapper接口开发的步骤:

/*
 * mybatis的Mapper接口的开发
 * 1.创建一个接口,接口的全路径要和Mapper文件的namespace相同
 * 2.mapper文件中每一个sql语句都要对应接口中的方法,并且sql的id值和方法名要相同
 * 3.接口中方法的返回值类型要和sql语句上的resultType值相同(方法若返回集合
 * 			resultType指定为集合中的泛型即可)
 * 4.接口中方法的参数类型要和sql语句上的参数类型相同
 */

 

解释.class的含义,在此处就是代表的是EmpMapper接口的class对象

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

mapper接口开发的介绍:

在上面的Mybatis案例中, 通过SqlSession对象调用方法进行增删改查操作时, 方法中需要传入的第一个参数是一个字符串值, 该值对应的内容为: (Mapper文件中的) namespace + id, 通过这种方式, 找到Mapper文件中映射的SQL语句并执行!!这种方式由于传入的是字符串值, 很容易发生字符串拼写错误且编译时期不会提示。这里我们将会讲解比上面更加简单的方式,也是我们企业开发中最常用的方式,即使用mapper接口开发。使用mapper接口开发需要注意以下几点:

1、创建一个接口,接口的全路径名和mapper文件的namespace值要相同
2、mapper文件中每条要执行的SQL语句,在接口中要添加一个对应的方法,并且接口中的方法名和SQL标签上的id值相同
3、Mapper接口中方法接收的参数类型,和mapper.xml中定义的sql的接收的参数类型要相同
4、接口中方法的返回值类型和SQL标签上的resultType即返回值类型相同(如果方法返回值是集合,resultType只需要指定集合中的泛型)

mapper开发接口的实现:

下面将使用mapper接口开发的方式,实现根据id查询指定的员工信息

1、创建com.tedu.dao.EmpMapper接口

由于接口的全路径名(com.tedu.dao.EmpMapper)要和EmpMapper.xml的namespace值保持一致, 因此, 这里将namespace的值改为com.tedu.dao.EmpMapper

<?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="com.tedu.dao.EmpMapper">

</mapper>

2、在接口中提供findById方法

/**
 * 根据id查询员工信息
 * @param id
 * @return Emp
 */
public Emp findById(Integer id);

注意:方法的名字要和映射的sql标签的id值保持一致方法的返回值类型和resultType的类型要一致

<!-- 1.查询:查询Emp表中指定id的员工信息 -->
<select id="findById" resultType="com.tedu.pojo.Emp">
	select * from emp where id=#{id}
</select>

3、提供实现类,测试Emp接口中的根据id查询员工的方法

(1)创建com.tedu.test.TestMybatisInf类, 并提供testFindById方法

public class TestMybatisInf {
	@Test
	public void testFindById() throws Exception{}
}

实现testFindById方法并测试

@Test
public void testFindById() throws Exception{
	......
	//3.获取Mapper接口对象
	EmpMapper map = session.getMapper(EmpMapper.class);
	//4.调用接口对象的方法进行查询
	Emp e = map.findById(2);
	//5.输出结果
	System.out.println(e);
}

5、在接口中提供findAll方法

/**
 * 查询所有的员工信息
 * @return List<Emp>
 */
public List<Emp> findAll();

注意:方法的名字要和映射的sql标签的id值保持一致,方法的返回值类型和resultType的类型要一致, 例如:

<!-- 2.查询Emp表中所有员工的信息 -->
<select id="findAll" resultType="com.tedu.pojo.Emp">
	select * from emp
</select>

6、提供实现类,测试Emp接口中的查询所有员工的方法

(1)创建com.tedu.test.TestMybatisInf类, 并提供testFindAll方法

public class TestMybatisInf {
	......
	@Test
	public void testFindAll () throws Exception{}
}

实现testFindAll方法并测试

@Test
public void testFindAll() throws Exception{
	...... 
	//3.获取Mapper接口对象
	EmpMapper map = session.getMapper(EmpMapper.class);
	//4.调用接口对象的方法进行查询
	List<Emp> list = map.findAll();
	//5.输出结果
	for (Emp e : list) {
		System.out.println(e);
	}
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值