编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
Maven版本:apache-maven-3.6.3
Mybatis版本:3.5.6
目录
- 一.详解Mybatis的核心配置文件【mybatis-config.xml】
- 1.1 核心配置文件概述
- 1.2 核心配置文件之根标签
- 1.3核心配置文件之常用子标签
- 1.3.1 properties子标签
- 1.3.2 settings 子标签
- 1.3.3 typeAliases(类型别名)子标签
- 1.3.3.1 Mybatis 常用的自定义别名
- 1.3.4 environments(环境配置)子标签
- 1.3.5 mappers(映射器)子标签
- 二. 详解Mybatis的映射文件
- 2.1 映射文件概述
- 2.2 映射文件之根标签
- 2.3 映射文件子标签
- 2.3.1 insert标签
- 2.3.2 delete标签
- 2.3.3 update标签
- 2.3.4 select标签
- 2.3.5 Sql标签
- 2.3.6 cache标签
- 2.3.7 cache-ref标签
- 2.3.8 resultMap标签
- 2.4 映射文件中常用的属性
- 2.4.1 resultType
- 2.5 获取主键自增数据
- 2.6 获取数据库受影响行数
一.详解Mybatis的核心配置文件【mybatis-config.xml】
1.1 核心配置文件概述
MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性等相关信息
1.2 核心配置文件之根标签
作用:
在根标签内部设置所有的子标签
语法:
<configuration>
</configuration>
1.3核心配置文件之常用子标签
1.3.1 properties子标签
作用:
可以定义属性或引入外部属性文件
为什么要引入外部属性文件?
实现数据库连接属性的解耦
应用场景:
①在properties 元素中设置相应属性
怎么设置?
在properties 元素的子元素中设置数据库连接对象的driver与与ur的属性值
设好的属性driver与url可以在dataSource标签下相同的属性中动态替换它们的属性值,如下图所示。
用法案例:在核心配置文件中使用properties子标签设置数据库连接需要的driver与url属性,将其属性值引用至environments标签下的dataSource子标签中相应的属性中,运行测试。
示例代码如下:
①在核心配置文件中使用properties子标签设置数据库连接需要的driver与url属性,将其属性值引用至environments标签下的dataSource子标签中相应的属性中
<properties>
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/0411db?serverTimezone=UTC"/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 下面是mysql8版本 -->
<property name="driver" value="${driver}"/>
<!-- url后要加时区 ?serverTimezone=UTC" ,不然报错 -->
<property name="url" value="${url}"/>
<!-- 下面是mysql5版本的写法
<property name="driver"value="com.mysql.jdbc.Driver"/>
<property name="url"value="jdbc:mysql://localhost:3306/0411db"/>
-->
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
②运行测试
②引入外部属性文件
如何在外部定义并引入数据库连接的属性文件?
- 例如在resources目录下定义一个db.properties文件,用以存放数据库连接的相关属性值
- 在核心配置文件中使用properties标签引入外部的属性文件db.properties
注意:properties标签内两种引用文件的方式resource与url)的区别,如下图所示:
示例代码如下:
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 下面是mysql8版本 -->
<property name="driver" value="${db.driver}"/>
<!-- url后要加时区 ?serverTimezone=UTC" ,不然报错 -->
<property name="url" value="${db.url}"/>
<!-- 下面是mysql5版本的写法
<property name="driver"value="com.mysql.jdbc.Driver"/>
<property name="url"value="jdbc:mysql://localhost:3306/0411db"/>
-->
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
1.3.2 settings 子标签
作用:
这是MyBatis中极为重要的调整设置,它会改变MyBatis的运行时行为。
常用属性:
mapUnderscoreToCamelCase属性
:是否开启驼峰命名自动映射,默认值为false,如设置true会自动将数据库中的字段a_col与Java对象中的aCol属性自动映射
注意:
只能将字母相同的字段与属性自动映射
示例代码如下;
a.在核心配置文件中的settings里未设置mapUnderscoreToCamelCase的值时:
b.在核心配置文件中设置mapUnderscoreToCamelCase的属性为true时:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
1.3.3 typeAliases(类型别名)子标签
作用:
类型别名可为Java类型设置一个别名
语法及特点:
①为Java pojo(Java bean【实体类】)设置别名(不常用)
<typeAliases>
//为指定类型定义别名,前者是类的全类名,后者是该类的别名(小名)
<typeAlias type="mybatis.mapper.EmployeeMapper" alias="employee"
</typeAliases>
②为指定包下的所有pojo起别名(常用)
<typeAliases>
//为指定包【mybatis.pojo】下所有的类定义别名。
//默认将类名作为别名,不区分大小写【推荐使用小写字母】
<package name="mybatis.pojo"/>
</typeAliases>
1.3.3.1 Mybatis 常用的自定义别名
别名 | 类型 |
---|---|
_int | int |
integer或int | Integer |
string | String |
list或arraylist | ArrayList |
map或hashmap | HashMap |
注:Java的其他基本数据类型与int的Mybatis自定义别名的命名风格雷同,包装类型也是如此,这里不做赘述。
1.3.4 environments(环境配置)子标签
作用:
设置数据库连接环境
示例代码如下:
//设置数据库的连接环境
<environments default="development">
//可设置多个<environment></environment>
<environment id="development">
//设置事务管理器的相应属性
<transactionManager type="JDBC"/>
//设置数据源
<dataSource type="POOLED">
//设置数据库连接的相应属性
<!-- 下面是mysql8版本 -->
//设置数据库连接的driver(驱动)
<property name="driver" value="${db.driver}"/>
<!-- url后要加时区 ?serverTimezone=UTC" ,不然报错 ->
//设置数据库连接的url
<property name="url" value="${db.url}"/>
<!-- 下面是mysql5版本的写法
<property name="driver"value="com.mysql.jdbc.Driver"/>
<property name="url"value="jdbc:mysql://localhost:3306/0411db"/>
-->
//设置数据库连接所需要的能够登录MySQL的用户名
<property name="username" value="root"/>
//设置密码
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
1.3.5 mappers(映射器)子标签
作用:
设置加载映射文件的路径
示例代码如下:
<mappers>
<mapper resource="mapper/EmployeeMapper.xml"/>
//有些老项目可能会这么写
<!--要求:接口的包名与陕射义件的包名需要致-->
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
注意:
核心配置文件中的子标签,是有顺序要求的
默认顺序如下:
不信,大可以试试!
二. 详解Mybatis的映射文件
2.1 映射文件概述
Mybatis的真正强大在于它的语句映射,这是它的魔力所在。如果拿它跟具有相同功能的JDBC代码进行对比,你会立即发现省掉了将近95%的代码。(摘自官方文档)
2.2 映射文件之根标签
根标签:mapper标签
注意:
mapper中的namespace要求与接口的全类名一致
如何获取接口(方法/ pojo)的全类名?
①将光标置于要获取的接口名上
如下图所示:
②鼠标右击打开下面的选项栏,点击"copy Reference“
③”mybatis.mapper.DeptMapper"就是刚才接口名的全名称
2.3 映射文件子标签
2.3.1 insert标签
功能:
定义添加sql语句
用法案例:
使用insert标签插入一条数据(employee对象)到数据库中
①在EmployeeMapper接口中先定义添加数据的方法
代码示例如下:
//添加员工
public void insertEmployee(Employee employee);
②在上述接口对应的映射文件中使用insert标签
代码示例如下:
<insert id="insertEmployee">
insert into
tbl_employee(last_name,email,salary)
<!-- 这里是要将employee对象中的属性值传到mysql中 -->
values(#{lastName},#{email},#{salary})
</insert>
③测试
@Test
public void testInsertEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
employeeMapper.insertEmployee(new Employee("张三","hdfjf@163.com",9000.0));
//开启事务,数据才能真正存进数据库中,why?
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
这里有一个问题:即使用mybatis,添加数据到MySQL数据库中时,代码中为什么要加sqlSession.commit()这句代码后,数据才能真正存进数据库中?
解释:
在使用 Mybatis 操作数据时,调用插入或更新方法后,SQL 语句并不会立即执行,而是被缓存到当前的 SqlSession 对象中。这个字面意义上的 Session 就像一个会话,预计会涉及多个数据库操作,其生命周期通常是跨越过多个请求和响应 (request,response) 阶段。
因此,如果想要将数据真正存入数据库中,需要手动触发一次提交 (commit) 动作。Mybatis 中 SqlSession 接口提供了 commit() 方法来提交事务,以便将所有未提交的 SQL 语句立即执行,并将结果存入数据库。
也就是说,sqlSession.commit() 可以将之前缓存的 SQL 语句批量地发送给数据库进行处理。同时,如果没有提交事务,之前所做的更改全部都将被回滚,并且数据库不会有任何变化。
因此,在使用 Mybatis 进行数据操作时,添加 sqlSession.commit() 这句代码是非常必要的,否则可能出现数据插入失败的情况。
2.3.2 delete标签
功能:
定义删除sql语句
用法案例:
使用delete标签在数据库中删除员工编号为4的数据
①在EmployeeMapper接口中先定义删除数据的方法
代码示例如下:
//删除员工(根据员工编号删除对应的员工信息)
public void deleteEmployee(int empId);
②在上述接口对应的映射文件中使用delete标签
代码示例如下:
<delete id="deleteEmployee">
delete from tbl_employee
where id= #{empId}
</delete>
③测试
代码示例如下:
@Test
public void testDeleteEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//删除员工编号为4的员工信息
employeeMapper.deleteEmployee(4);
//开启事务,数据才能真正存进数据库中
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
2.3.3 update标签
功能:
定义修改sql语句
用法案例:
使用update标签修改员工编号为2的相关员工数据
修改前的数据:
①在EmployeeMapper接口中先定义修改数据的方法
代码示例如下:
//修改员工数据
public void updateEmployee(Employee employee);
②在上述接口对应的映射文件中使用update标签
代码示例如下:
<update id="updateEmployee">
update tbl_employee
set email=#{email} , salary=#{salary}
where id=#{id}
</update>
③测试
@Test
public void testUpdateEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//通过调用代理对象去执行删除,这点和当初在Dao层新建接口,接口的实现类去实现删除的功能很像,代理对
//象就相当于当初接口的实现类一样,但是我并没有写接口的实现类,但在mybatis框架中就真真切切的实现了
//删除的功能,究其原因,应该是mybatis在底层就帮我实现了,但是具体是怎么实现的,我暂时不知道
//修改员工编号为2的员工部分信息
employeeMapper.updateEmployee(new Employee(2,"hdjs@qq.com",120.0));;
//开启事务,数据才能真正存进数据库中
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
2.3.4 select标签
功能:
定义查询sql语句
用法案例:
使用select标签查询数据库中所有的员工信息
①在EmployeeMapper接口中先定义查看所有的员工数据的方法
代码示例如下:
//查看所有的员工信息
public List<Employee> showAllEmployee();
②在上述接口对应的映射文件中使用select标签
代码示例如下:
<!-- 查看所有的员工信息 -->
<!-- 如果resultType中的值是一个类的类型,如果之前定义它的别名,这里可填写该类的别名,毕竟有时类的全名太长了 -->
<select id="showAllEmployee" resultType="mybatis.pojo.Employee">
select
id,
last_name ,
email,
salary
from
tbl_employee
</select>
注意:
在resultType中,期望从这条语句中返回结果的类全限定名或别名,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用
③测试
@Test
public void testShowAllEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = employeeMapper.showAllEmployee();
for (Employee employee : employees) {
System.out.println(employee);
}
/*
//开启事务,数据才能真正存进数据库中
sqlSession.commit();
*/
} catch (IOException e) {
e.printStackTrace();
}
}
备注:以下子标签的详细功能用法将在接下来的序列文章中详细探讨,这里不做赘述
2.3.5 Sql标签
功能:
定义可重用的SQL语句块
2.3.6 cache标签
功能:
设置当前命名空间的缓存配置
2.3.7 cache-ref标签
功能:
设置其他命名空间的缓存配置
2.3.8 resultMap标签
功能:
描述如何从数据库结果集中加载对象
注意:
在使用多表查询的场景上,resultType解决不了,就用resultMap
2.4 映射文件中常用的属性
2.4.1 resultType
功能描述:
设置期望结果集返回类型【全类名或别名】
注意:
如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。
resultType和resultMap之间只能同时使用一个
2.5 获取主键自增数据
获取主键自增数据需要用到以下两个属性
-
useGeneratedKeys
:启用主键生成策略 -
keyProperty
:设置存储属性值
用法案例:基于EmployeeMapper接口中的插入数据的方法,对其映射文件中原有的insert标签内,添加以上两个属性,使在插入数据时获得其自增主键
①在EmployeeMapper接口中书写插入数据的方法
代码示例如下:
//添加员工
public void insertEmployee(Employee employee);
②在EmployeeMapper接口对应的映射文件中对使用inset标签添加获取主键自增数据的两个属性
代码示例如下:
<!-- useGeneratedKeys="true" keyProperty="id" : 启用主键生成策略,返回的结果集中包含自动生成主键的信息,并将其赋值给实体类对象中的 id 属性 -->
<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="id">
insert into
tbl_employee(last_name,email,salary)
<!-- 这里是要将employee对象中的属性值传到mysql中 -->
values(#{lastName},#{email},#{salary})
</insert>
③测试
代码示例如下
@Test
public void testInsertKeyEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee=new Employee("李四1","sshdfjf@163.com",9000.0);
employeeMapper.insertEmployee(employee);
//当执行插入sql后,获取新增员工的主键(员工编号)
System.out.println("employee.getId() : "+employee.getId());
//开启事务,数据才能真正存进数据库中
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
2.6 获取数据库受影响行数
如何获取数据库受影响行数?
直接将接口中相应方法的返回值设置为int或boolean即可
-
int
:代表受影响行数 -
boolean
:代表是否影响了数据库,true代表影响了数据库,false则代表无
用法案例:在插入数据时获取数据库受影响的行数
①基于2.5小节中用法案例的代码,仅仅修改Mapper接口中返回值的类型为int
代码示例如下:
//修改Mapper接口中返回值的类型为int
//添加员工
public int insertEmployee(Employee employee);
②测试代码做相应的微调并测试
//测试代码做相应的微调
@Test
public void testInsertKeyEmployee(){
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过SqlSessionFactory对象调用openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取EmployeeMapper的代理对象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee=new Employee("李四1","sshdfjf@163.com",9000.0);
//获取返回值i(影响数据库的行数)
int i = employeeMapper.insertEmployee(employee);
System.out.println("影响数据库的行数: "+i);
//当执行插入sql后,获取新增员工的主键(员工编号)
System.out.println("employee.getId() : "+employee.getId());
//开启事务,数据才能真正存进数据库中
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
}
}