知识点梳理
详细讲义
一.Mybatis快速入门
1.1 框架介绍
-
框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们个性化的需求!
-
框架:大工具,我们利用工具,可以快速开发项目 (mybatis也是一个jar包,不过提供的功能更加多)
-
jar包:小工具
-
如图:
-
生活中的例子,比如盖房子
-
张三想盖红色的房子,他需要先给架构搭起来,然后再给房子图上红色
-
李四想盖蓝色的房子,他也需要先给架构搭起来,然后再给房子图上蓝色
-
比如很多人都需要盖房子,那么肯定会有很多重复性的工作,比如说基础架构
-
这时候就有公司出了一个解决方案,准备好了房子的架构(上图左下角黑色的),谁需要盖房子,只需要借助于公司提供的架构,在这个基础之上进行装修,涂色即可
-
1.2 ORM介绍 ***
-
ORM(Object Relational Mapping): 对象关系映射
-
object:指的是实体对象,javabean
-
relational:指的是关系型数据库,比如mysql
-
Mapping: 映射,一 一对应的关系
-
-
指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术。
-
如图:
-
简单说,ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写
-
ORM 把数据库映射成对象,具体映射关系如下图:
1.3 原始jdbc操作(查询数据)
1.4原始jdbc操作(插入数据)
1.5 原始jdbc操作的分析
-
原始 JDBC 的操作问题分析
1. 频繁创建和销毁数据库的连接会造成系统资源浪费从而影响系统性能
-
sql 语句在代码中硬编码,如果要修改 sql 语句,就需要修改 java 代码,造成代码不易维护
-
查询操作时,需要手动将结果集中的数据封装到实体对象中
-
增删改查操作需要参数时,需要手动将实体对象的数据设置到 sql 语句的占位符
-
-
原始 JDBC 的操作问题解决方案
1. 使用数据库连接池初始化连接资源
-
将 sql 语句抽取到配置文件中
-
使用反射、内省等底层技术,将实体与表进行属性与字段的自动映射
-
通过分析原始jdbc操作存在的问题,以及对应的解决方案,那么在对应的解决方案在完全可以使用MyBatis替代
-
1.6 什么是Mybatis
-
mybatis 是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程
-
mybatis通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句
-
最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作
-
MyBatis官网地址:http://www.mybatis.org/mybatis-3/
1.7 Mybatis的快速入门 ***
MyBatis开发步骤:
①添加MyBatis的jar包
②创建Student数据表
③编写Student实体类
④编写映射文件StudentMapper.xml
⑤编写核心文件MyBatisConfig.xml
⑥编写测试类
1.7.1 环境搭建
0) 新建java项目:mybatis01
1) 导入MyBatis的jar包 (在”今日资料jar包“ 中,将jar包导入项目libs下)
-
mysql-connector-java-5.1.37-bin.jar
-
mybatis-3.5.3.jar
-
log4j-1.2.17.jar
2) 创建student数据表
3) 编写Student实体
package com.itheima.bean;
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get个set方法
}
4) 新建测试类
package com.itheima.dao;
public class StudentTest01 {
/*
查询全部
*/
5) 编写src/StudentMapper.xml映射文件
6) 编写MyBatis核心文件: src/MyBatisConfig.xml
1.7.2 编写测试代码
1.8 知识小结
-
框架
框架是一款半成品软件,我们可以基于框架继续开发,从而完成一些个性化的需求。
-
ORM
对象关系映射,数据和实体对象的映射。
-
MyBatis
是一个优秀的基于 Java 的持久层框架,它内部封装了 JDBC。
二.MyBatis的相关api ***
2.1 Resources
-
org.apache.ibatis.io.Resources:加载资源的工具类
-
mybatis的前身就是ibatis
-
-
核心方法
-
如果不使用Resources,那我们可以自己使用类加载器(但是麻烦)
//InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
InputStream is = StudentTest01.class.getClassLoader().getResourceAsStream("MyBatisConfig.xml");
2.2 构建器SqlSessionFactoryBuilder
-
org.apache.ibatis.session.SqlSessionFactoryBuilder:获取 SqlSessionFactory 工厂对象的功能类
-
核心方法
-
通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory fact ory = builder.build(inputStream);
2.3 工厂对象SqlSessionFactory
-
org.apache.ibatis.session.SqlSessionFactory:获取 SqlSession 构建者对象的工厂接口。
-
核心api
-
代码
//3.通过SqlSession工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.执行映射配置文件中的sql语句,并接收结果
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");-
说明:因为我们的代码是执行了一个查询的语句,所以不用处理事务
-
2.4 SqlSession会话对象 ***
-
org.apache.ibatis.session.SqlSession:构建者对象接口。用于执行 SQL、管理事务、接口代理。
-
核心api
-
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法
-
作用:
-
通过SqlSession对象,主要用途执行sql语句,对数据库进行操作
-
-
本质:
-
SqlSession 可以理解为相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务
-
所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try...catch...finally... 语句来保证其正确关闭
-
2.5 小结
-
Resources
-
加载资源的工具类
-
-
SqlSessionFactoryBuilder
-
获取 SqlSessionFactory 工厂对象的功能类
-
-
SqlSessionFactory
-
获取 SqlSession 构建者对象的工厂接口
-
指定事务的提交方式
-
-
SqlSession
-
构建者对象接口
-
执行 SQL
-
管理事务
-
接口代理
-
三.MyBatis 映射配置文件 ***
3.1 映射配置文件介绍
-
映射配置文件包含了数据和对象之间的映射关系以及要执行的 SQL 语句
-
这个namespace,命名空间,相当于是给这个映射节点,起一个名字
-
内部的所有增删改查的配置,都需要通过这个命名空间获取
-
语法:命名空间.id
-
3.2 查询功能
-
<select>
:查询功能标签 -
属性
id:唯一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
-
SQL 获取参数: #{属性名}
-
修改StudentMapper.xml,增加如下:
-
因为参数类型是Integer,所以属性名可以改名字(#{sid})
-
但是这里的属性名一般是与数据库列名一致的
-
为啥叫属性名,其实应该是参数名,但是这个参数名一般都是与javabean中的属性名保持一致的,所以叫属性名
-
-
-
测试类StudentTest01.java,新增代码:
/*
根据id查询
*/
####3.3 新增功能
-
<insert>
:新增功能标签 -
属性
id:唯一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
-
SQL 获取参数: #{属性名} #{列名}
-
修改StudentMapper.xml,增加如下:
-
注意:因为这里的参数类型是Student,所以属性名必须与Student的字段保持一致
-
-
测试类StudentTest01.java,新增代码:
/*
新增功能
*/
3.4 修改功能
-
<update>
:修改功能标签 -
属性
id:唯一标识, 配合名称空间使用
parameterType:指定参数映射的对象类型
resultType:指定结果映射的对象类型
-
SQL 获取参数: #{属性名}
-
修改StudentMapper.xml,增加如下:
-
注意:因为这里的参数类型是Student,所以属性名必须与Student的字段保持一致
-
-
测试类StudentTest01.java,新增代码:
/*
修改功能
*/
3.5 删除功能
-
<delete>
:查询功能标签。 -
属性
id:唯一标识, 配合名称空间使用。
parameterType:指定参数映射的对象类型。
resultType:指定结果映射的对象类型。
-
SQL 获取参数: #{属性名}
-
修改StudentMapper.xml,增加如下:
-
测试类StudentTest01.java,新增代码:
/*
删除功能
*/
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.执行映射配置文件中的sql语句,并接收结果
int result = sqlSession.delete("StudentMapper.delete",5);
//5.提交事务
sqlSession.commit();
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
} -
总结: 大家可以发现crud操作,除了标签名称以及sql语句不一样之外,其他属性参数基本一致。
3.6 映射配置文件小结
四.Mybatis核心配置文件介绍 ***
4.1 核心配置文件介绍
核心配置文件包含了 MyBatis 最核心的设置和属性信息。如数据库的连接、事务、连接池信息等。
如下图:
4.2 数据库连接配置文件引入
-
properties标签作用:
-
引入外部的数据库配置文件
-
-
标签属性
-
resource:数据库连接配置文件路径
-
-
获取数据库连接参数的语法格式
-
${键名}
-
-
优点
-
便于灵活的修改数据库连接池配置参数.
-
-
创建:src/jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=rooot
password=itheima -
修改MyBatisConfig.xml配置文件:properties标签引入外部文件
<!--引入数据库连接的配置文件-->
<properties resource="jdbc.properties"/>
<!-- property获取数据库连接的配置信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
4.3 起别名
-
<typeAliases>
:为全类名起别名的父标签。 -
<typeAlias>
:为全类名起别名的子标签。 -
属性
type:指定全类名
alias:指定别名 ([ˈeɪliəs]:别名)
-
<package>
:为指定包下所有类起别名的子标签。(别名就是类名) -
如下图:
-
具体如下配置:修改MyBatisConfig.xml,增加代码如下:
<!--起别名-->
<typeAliases>
<typeAlias type="com.itheima.bean.Student" alias="student"/>
<!--<package name="com.itheima.bean"/>
如果bean包下有很多Javabean都需要起别名,就可以使用package,指定一个包名
这样的话,就自动给这个包下所有的类添加别名,别名是类名的小写名字
-->
</typeAliase>
</typeAliases> -
然后使用的时候就方便了,修改StudentMapper.xml中的com.itheima.bean.Student
<select id="selectAll" resultType="student"> SELECT * FROM student </select> <select id="selectById" resultType="student" parameterType="int"> SELECT * FROM student WHERE id = #{id} </select> <insert id="insert" parameterType="student"> INSERT INTO student VALUES (#{id},#{name},#{age}) </insert> <update id="update" parameterType="student"> UPDATE student SET name = #{name},age = #{age} WHERE id = #{id} </update> <delete id="delete" parameterType="int"> DELETE FROM student WHERE id = #{id} </delete>
4.4 总结
五.Mybatis传统方式开发
5.1 Dao 层传统实现方式
-
分层思想:控制层(controller)、业务层(service)、持久层(dao)。
-
调用流程
5.1.1 准备工作
-
实现步骤
-
在controller包下: 新建StudentContoller类
-
在service包下: 新建StudentService接口以及StudentServiceImpl实现类
-
在mapper包下:新建StudentMapper接口以及StudentMapperImpl实现类
-
StudentContoller----->StudentService----->StudentMapper
-
-
在mybatis项目中持久层就不再叫dao了,而是叫做mapper(其实都是一样的,就是换个名字)
-
StudentMapper接口
package com.itheima.mapper; import com.itheima.bean.Student; import java.util.List; /* 持久层接口 */ public interface StudentMapper { //查询全部 public abstract List<Student> selectAll(); //根据id查询 public abstract Student selectById(Integer id); //新增数据 public abstract Integer insert(Student stu); //修改数据 public abstract Integer update(Student stu); //删除数据 public abstract Integer delete(Integer id); }
-
StudentMapperImpl实现类
package com.itheima.mapper.impl; /* 持久层实现类 */ public class StudentMapperImpl implements StudentMapper { /* 查询全部 */ @Override public List<Student> selectAll() { } /* 根据id查询 */ @Override public Student selectById(Integer id) { } /* 新增功能 */ @Override public Integer insert(Student stu) { } /* 修改功能 */ @Override public Integer update(Student stu) { } /* 删除功能 */ @Override public Integer delete(Integer id) { } }
-
StudentService接口
package com.itheima.service; import com.itheima.bean.Student; import java.util.List; /* 业务层接口 */ public interface StudentService { //查询全部 public abstract List<Student> selectAll(); //根据id查询 public abstract Student selectById(Integer id); //新增数据 public abstract Integer insert(Student stu); //修改数据 public abstract Integer update(Student stu); //删除数据 public abstract Integer delete(Integer id); }
-
StudentServiceImpl实现类
package com.itheima.service.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.mapper.impl.StudentMapperImpl; import com.itheima.service.StudentService; import java.util.List; /* 业务层实现类 */ public class StudentServiceImpl implements StudentService { //创建持久层对象 private StudentMapper mapper = new StudentMapperImpl(); @Override public List<Student> selectAll() { return mapper.selectAll(); } @Override public Student selectById(Integer id) { return mapper.selectById(id); } @Override public Integer insert(Student stu) { return mapper.insert(stu); } @Override public Integer update(Student stu) { return mapper.update(stu); } @Override public Integer delete(Integer id) { return mapper.delete(id); } }
-
StudentController测试类:
package com.itheima.controller; import com.itheima.bean.Student; import com.itheima.service.StudentService; import com.itheima.service.impl.StudentServiceImpl; import org.junit.Test; import java.util.List; /* 控制层测试类 */ public class StudentController { //创建业务层对象 private StudentService service = new StudentServiceImpl(); //查询全部功能测试 @Test public void selectAll() { List<Student> students = service.selectAll(); for (Student stu : students) { System.out.println(stu); } } //根据id查询功能测试 @Test public void selectById() { Student stu = service.selectById(3); System.out.println(stu); } //新增功能测试 @Test public void insert() { Student stu = new Student(4,"赵六",26); Integer result = service.insert(stu); System.out.println(result); } //修改功能测试 @Test public void update() { Student stu = new Student(4,"赵六",16); Integer result = service.update(stu); System.out.println(result); } //删除功能测试 @Test public void delete() { Integer result = service.delete(4); System.out.println(result); } }
5.1.2 持久层功能实现
工具类抽取:
package com.itheima.utils; 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 java.io.IOException; /* 工具类 */ public class MyBatisUtils { // 私有构造方法 private MyBatisUtils(){} // 声明连接工厂对象 private static SqlSessionFactory sqlSessionFactory; // 静态代码块,读取核心配置文件并工厂对象赋值 static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("MyBatisConfig.xml")); } catch (IOException e) { e.printStackTrace(); } } // 提供静态方法,返回SqlSession对象 public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
StudentMapperImpl代码:
package com.itheima.mapper.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import java.util.List; /* 持久层实现类 */ public class StudentMapperImpl implements StudentMapper { /* 查询全部 */ @Override public List<Student> selectAll() { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectAll"); // 释放资源 sqlSession.close(); // 返回结果 return list; } /* 根据id查询 */ @Override public Student selectById(Integer id) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Student stu = sqlSession.selectOne("StudentMapper.selectById", id); // 释放资源 sqlSession.close(); // 返回结果 return stu; } /* 新增功能 */ @Override public Integer insert(Student stu) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.insert("StudentMapper.insert", stu); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 修改功能 */ @Override public Integer update(Student stu) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.update("StudentMapper.update", stu); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 删除功能 */ @Override public Integer delete(Integer id) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 Integer result = sqlSession.delete("StudentMapper.delete", id); // 释放资源 sqlSession.close(); // 返回结果 return result; } /* 查询指定的数据表 */ @Override public List<Student> selectByTableName(String tableName) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectByTableName",tableName); // 释放资源 sqlSession.close(); // 返回结果 return list; } /* 模糊查询 */ @Override public List<Student> selectLike(String condition) { // 获取SqlSession对象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 执行sql语句 List<Student> list = sqlSession.selectList("StudentMapper.selectLike",condition); // 释放资源 sqlSession.close(); // 返回结果 return list; } }
5.2 LOG4J的配置和使用
-
在日常开发过程中,排查问题时难免需要输出 MyBatis 真正执行的 SQL 语句、参数、结果等信息,我们就可以借助 LOG4J 的功能来实现执行信息的输出。
-
使用步骤:
-
导入 jar 包:“01-MyBatis基础资料jar包log4j-1.2.17.jar”
-
修改核心配置文件:MyBatisConfig.xml
<!--配置LOG4J:以下name和value是固定写法--> <settings> <setting name="logImpl" value="log4j"/> </settings>
-
在 src 下编写 LOG4J 配置文件 : log4j.properties (配置文件名字也是固定写法)
# Global logging configuration # 日志的四个级别,从高到低:ERROR(错误信息) WARN(警告信息) INFO(普通信息) DEBUG(调试信息,推荐使用) # stdout:输出到控制台 log4j.rootLogger=DEBUG, stdout # 输出格式 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
-
效果
-
错误:
Caused by: org.xml.sax.SAXParseException; lineNumber: 41; columnNumber: 17; 元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。
这个是因为configuration下的节点顺序是有要求的,settings必须是在properties下,放在其他位置会报错。
-