学习笔记MyBatis学习笔记
Posted 棉花糖灬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记MyBatis学习笔记相关的知识,希望对你有一定的参考价值。
本文是动力节点MyBatis教程的学习笔记。
第一章
1. 三层架构
(1) 三层的功能
-
表示层(User Interface Layer):接受用户数据,显示请求的处理结果,包括jsp、html、servlet等。对应controller包;
-
业务逻辑层(Business Logic Layer):接受表示层传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。对应service包;
-
数据访问层(Data Access Layer,DAL):也称持久层,与数据库打交道。对应DAO包。
(2) 三层中类的交互
用户使用表示层 --> 业务逻辑层 --> 数据访问层 --> 数据库
(3) 三层对应的处理框架
表示层 ---- servlet ---- SpringMVC框架
业务逻辑层 ---- service类 ---- Spring框架
数据访问层 ---- DAO类 ---- MyBatis框架
2. JDBC编程
(1) JDBC实例
public void findStudent()
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try //注册mysql驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据的基本信息 url ,username,password
String url = "jdbc:mysql://localhost:3306/springdb";
String username = "root";
String password = "123456";
// 创建连接对象
conn = DriverManager.getConnection(url, username, password);
// 保存查询结果
List<Student> stuList = new ArrayList<>();
// 创建Statement, 用来执行sql语句
stmt = conn.createStatement();
// 执行查询,创建记录集,
rs = stmt.executeQuery("select * from student");
while (rs.next())
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
// 从数据库取出数据转为Student对象,封装到List集合
stuList.add(stu);
catch (Exception e)
e.printStackTrace();
finally
try
//关闭资源
if (rs != null) ;
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
catch (Exception e)
e.printStackTrace();
(2) JDBC缺点
- 代码较多,开发效率低
- 需要关注Connection、Statement、ResultSet对象的创建和销毁
- 对ResultSet查询的结果,需要自己封装为List
- 重复的代码多
- 业务代码和数据库操作混在一起
3. MyBatis框架概述
(1) MyBatis功能
SQL映射:可以把数据库表中的一行数据,映射为一个java对象,操作这个对象,就相当于操作表中的数据。
数据访问:对数据库执行增删改查
- 注册数据库的驱动
- 创建 JDBC中必须使用的Connection、Statement、ResultSet对象
- 从 xml中获取中获取sql,执行sql语句,把ResultSet结果转换为java对象
- 关闭资源
(2) 入门案例
项目名为01-helloMyBatis,目录的结构如下:
1) 创建student表并插入数据
在MySQL的mybatis库中创建student表:
CREATE TABLE `student` (
`id` int NOT NULL,
`name` varchar(80) NOT NULL,
`email` varchar(100) NOT NULL,
`age` int NOT NULL,
PRIMARY KEY (`id`,`age`)
) ENGINE=InnoDB;
INSERT INTO `student` VALUES ('1001', '李四', 'lisi@qq.com', '11');
INSERT INTO `student` VALUES ('1002', '张三', 'zhangsan@126.com', '12');
2) 加入maven的MyBatis坐标,MySQL驱动的坐标
创建maven工程,在pom.xml文件中添加以下依赖
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
其中版本号可以不一样,lombok提供的@Data注解可以为实体类添加get、set、toString方法等,以简化代码。
3) 创建实体类Student
package cn.ecnu.domain;
import lombok.Data;
// 推荐和表名一样,方便记忆
@Data
public class Student
// 定义属性,目前要求属性名和列名一致
private Integer id;
private String name;
private String email;
private Integer age;
4) 创建持久层的DAO接口,定义操作数据库的方法
package cn.ecnu.dao;
import cn.ecnu.domain.Student;
import java.util.List;
// 接口操作student表
public interface StudentDAO
// 查询student表的所有的数据
public List<Student> selectStudents();
5) 创建一个MyBatis使用的配置文件
也叫做SQL映射文件:写sql语句,一般一个表一个sql映射文件,为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="cn.ecnu.dao.StudentDAO">
<!--
id:要执行的sql语句的唯一标识,mybatis会使用这个id的值来找到要执行的sql语句,可以自定义,但要求使用接口中的方法名称
resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型,值写类型的全限定名称
-->
<select id="selectStudents" resultType="cn.ecnu.domain.Student">
select id,name,email,age from student order by id;
</select>
</mapper>
<!--
SQL映射文件:写sql语句,mybatis会执行这些sql
1. 指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的
2. 约束文件的作用:限制、检查在当前文件中出现的标签、属性必须符合mybatis的要求
3. mapper是当前文件的根标签,必须的
namespace:命名空间,唯一值,可以是自定义的字符串。要求使用DAO接口的全限定名称
4. 在当前文件中,可以使用特定的标签,表示数据库的特定操作
<select>:表示执行查询
<update>:表示更新数据库的操作,在里面写的是update语句
<insert>:表示插入,在里面写的是insert语句
<delete>:表示删除,在里面写的是delete语句
-->
6) 创建MyBatis的主配置文件
一个项目一个主配置文件,主配置文件提供了数据库的链接信息和sql映射文件的位置信息
<?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>
<!--
环境配置:数据的链接信息
default:必须和某个environment的id值一样,用来告诉mybatis使用按个数据库的连接信息,也就访问哪个数据库
-->
<environments default="mysql">
<!--
environment:一个数据库信息的配置,环境
id:数据源的名称,一个唯一值,自定义
-->
<environment id="mysql">
<!--
transationManager:mybatis的事务类型
type:JDBC(表示使用jdbc中的Connection对象的commit、rollback做事务处理)
-->
<transactionManager type="JDBC"/>
<!--
dataSource:数据源,用来链接数据库
type: POOLED,表示使用数据库的连接池
-->
<dataSource type="POOLED">
<!--连接数据库的四个要素-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- sql映射文件的位置 -->
<mappers>
<!--一个mapper标签指定一个文件的位置,从类路径开始的路径信息-->
<mapper resource="cn/ecnu/dao/StudentDAO.xml"/>
</mappers>
</configuration>
<!--
mybatis的主配置文件:主要定义了数据的配置信息,sql映射文件的位置
1. 约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
mybatis-3-config.dtd:约束文件的名称
2. configuration:根标签
-->
写好mybatis的配置文件后,resources下面的资源会在maven的compile的时候自动打包到target目录下,但StudentDAO.xml不会自动打包,需要在pom.xml中设置要扫描的配置文件的位置
<build>
<resources>
<resource>
<!-- 所在的目录 -->
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
7) 创建使用MyBatis类
通过MyBatis访问数据库
package cn.ecnu;
import cn.ecnu.domain.Student;
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;
import java.io.InputStream;
import java.util.List;
public class MyApp
public static void main(String[] args) throws IOException
// 访问mybatis读取student数据
// 1. 定义mybatis主配置文件的名称,从类路径的根开始(target/classes)
String config="mybatis.xml";
// 2. 读取config表示的文件
InputStream in = Resources.getResourceAsStream(config);
// 3. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
// 4. 创建SqlSessionFactory对象
SqlSessionFactory factory=builder.build(in);
// 5. 【重要】获取SqlSession对象,从SqlSessionFactory中获取SqlSession
SqlSession sqlSession = factory.openSession();
// 6. 【重要】指定要执行的sql语句的标识,sql映射文件中的namespace + "." + 标签的id值
String sqlId="cn.ecnu.dao.StudentDAO"+"."+"selectStudents";
// 7. 执行sql语句,通过sqlId找到语句
List<Student> studentList=sqlSession.selectList(sqlId);
// 8. 输出结果
studentList.forEach(System.out::println);
// 9. 关闭SqlSession对象
sqlSession.close();
运行得到的输出结果就是数据库中插入的两条数据。
(3) 插入数据
在StudentDAO.java接口中添加插入对应的方法:
// 插入方法
/*
* 参数:student为插入的数据
* 返回值:插入的记录数
* */
public int insertStudent(Student student);
在StudentDAO.xml中添加插入方法对应的sql语句:
<insert id="insertStudent">
insert into student values(#id,#name,#email,#age);
</insert>
其中#属性名是从insertStudent方法的入参student类中取得的属性值。
MyApp.java的6、7、8步需要修改,其他不变:
// 6. 【重要】指定要执行的sql语句的标识,sql映射文件中的namespace + "." + 标签的id值
String sqlId = "cn.ecnu.dao.StudentDAO" + "." + "insertStudent";
// 7. 执行sql语句,通过sqlId找到语句
Student student = new Student();
student.setId(1003);
student.setName("张飞");
student.setEmail("zhangfei@sina.com");
student.setAge(21);
int num = sqlSession.insert(sqlId, student);
// mybatis默认是不自动提交事务的,所以insert、update、delete后要手动提交事务
sqlSession.commit();
// 8. 输出结果
System.out.println("执行insert的结果: " + num);
第二章
1. 主要类的介绍
(1) Resources
mybatis中的一个类,负责读取主配置文件
InputStream in = Resources.getResourceAsStream(config);
(2) SqlSessionFactoryBuilder
创建SqlSessionFactory对象
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
(3) SqlSessionFactory
重量级对象,程序创建一个对象耗时较长,使用资源比较多。在整个项目中,有一个就够用了
SqlSessionFactory接口的实现类为DefaultSqlSessionFactory
SqlSessionFactory作用:获取SqlSession对象
SqlSession sqlSession = factory.openSession();
openSession()方法说明:
- openSession():无参数的,获取非自动提交事务的SqlSession对象
- openSession(boolean):当入参为true时,获取自动提交事务的SqlSession,反之为非自动提交事务的
(4) SqlSession
SqlSession接口:定义了操作数据的方法,例如selectOne()、selectList()、insert()、update()、delete()、commit()、rollback()等
SqlSession接口的实现类为DefaultSqlSession
使用需求:SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象,在执行完sql语句之后,需要执行SqlSession.close()来关闭它,这样能保证它的使用是线程安全的
2. 传统DAO使用方式
为StudentDAO接口增加对应的实现类,把业务逻辑代码放到实现类里,而不是直接放到main方法或者单元测试方法中。项目名为02-MyBatisUtils,代码组织结构如下:
实现类文件StudentDAOImpl.java中的内容为:
package cn.ecnu.dao.impl;
import cn.ecnu.dao.StudentDAO;
import cn.ecnu.domain.Student;
import cn.ecnu.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class StudentDAOImpl implements StudentDAO
@Override
public List<Student> selectStudents()
// 获取SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//【重要】指定要执行的sql语句的标识,sql映射文件中的namespace + "." + 标签的id值
String sqlId = "cn.ecnu.dao.StudentDAO" + "." + "selectStudents";
// 执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
// 关闭SqlSession对象
sqlSession.close();
return studentList;
@Override
public int insertStudent(Student student)
// 获取SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//【重要】指定要执行的sql语句的标识,sql映射文件中的namespace + "." + 标签的id值
String sqlId = "cn.ecnu.dao.StudentDAO" + "." + "insertStudent";
// 执行sql语句,通过sqlId找到语句
int num = sqlSession.insert(sqlId, student);
// mybatis默认是不自动提交事务的,所以insert、update、delete后要手动提交事务
sqlSession.commit();
return num;
单元测试文件StudentTest.java中的内容为:
package cn.ecnu;
import cn.ecnu.dao.StudentDAO;
import cn.ecnu.dao.impl.StudentDAOImpl;
import cn.ecnu.domain.Student;
import org.junit.Test;
import java.util.List;
public class StudentTest
@Test
public void selectStudentsTest()
StudentDAO dao = new StudentDAOImpl();
/*
* List<Student> studentList = dao.selectStudents(); 调用
* 1. dao对象,雷翔是SudentDAO,全限定名称是:cn.ecnu.dao.StudentDAO
* 全限定名称和namespace是一样的
*
* 2. 方法名称,selectStudents,这个方法是mapper文件中的id值
*
* 3. 通过dao中方法的返回值也可以确定MyBatis要调用的SqlSession的方法
* 如果返回值是List,调用的是SqlSession.selectList()方法
* 如果返回值非List的,如int,看mapper中的标签是<insert>、<update>就会调用
* SqlSession的insert、update等方法
*
* MyBatis的动态代理:MyBatis根据dao的方法调用,获取执行sql语句的信息。
* MyBatis根据dao接口,创建出一个dao接口的实现类,并创建这个类的对象,
* 完成SqlSession调用方法,访问数据库。
* */
List<Student> studentList = dao.selectStudents();
studentList.forEach(System.out::println);
@Test
public void insertStudentTest()
Student student = new Student();
student.setId(1004);
student.setName("刘备");
student.setEmail("liubei@sina.com");
student.setAge(22);
StudentDAO dao = new StudentDAOImpl();
int num = dao.insertStudent(student);
System.out.println("insert操作的执行结果:" + num);
其他文件和之前的保持一致。