MyBatis 学习日记(1)
MyBatis 三层架构
三层架构包括:界面层(User Interface Layer),业务逻辑层(Business Logic Layer),数据访问层(Data access Layer)。
1、界面层:主要是接收用户的数据,显示请求的处理结果。使用 web 页面和用户交互。
2、业务交互层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据库访问层获取数据。
3、数据访问层:与数据库打交道。主要实现对数据的增删改查,将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。
三层对应的包
1、界面层:controller 包(servlet)
2、业务逻辑层:service 包(XXXService类)
3、数据访问层:dao 包(XXXDao类)
三层中类的交互
用户使用界面层 -> 业务逻辑层 -> 数据访问层(持久层) -> 数据库(mysql)
三层对应的处理框架
1、界面层 - servlet - spring mvc 框架
2、业务逻辑层 - service 类 - spring 框架
3、数据访问层 - dao 类 - mybatis 框架
JDBC 缺陷
1、代码比较多,开发效率低
2、需要关注 Connection,Statement,Resultset 对象创建和销毁
3、对 ResultSet 查询的结果,需要自己封装为 List
4、重复的代码比较多
5、业务代码和数据库的操作混合在一起
MyBatis 解决的问题
MyBatis 原本是 apache 的一个开源项目 iBatis,2010 这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis。
MyBatis 减轻了使用 JDBC 的复杂性,不用编写重复的创建 Connection,Statement;不用编写关闭资源代码。直接使用 java 对象,表示结果数据。
MyBatis 可以完成
1、注册数据库的驱动,例如 Class.forName("com.mysql.jdbc.Driver")
2、创建 JDBC 中必须使用的 Connection,Statement,ResultSet 对象
3、从 xml 中获取 JDBC,并执行 sql 语句,把 ResultSet 结果转换为 java 对象
4、提供了关闭资源的能力
开发人员做的是:提供 sql 语句
最终流程:开发人员提供 sql 语句 - mybatis 处理 sql - 开发人员得到 List 集合或 java 对象 (表中的数据)
MyBatis 使用步骤
下载 mybatis
https://github.com/mybatis/mybatis-3/releases
创建 mysql 数据库和表
库名 ssm : 表名 student
CREATE DATABASE ssm;
CREATE TABLE student (
id INT(11) NOT NULL,
`name` VARCHAR(255) DEFAULT NULL,
`email` VARCHAR(255) DEFAULT NULL,
`age` INT(11) DEFAULT NULL,
PRIMARY KEY (id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
创建 Maven 项目
ch01-hello-mybatis: 第一个入门的 mybatis 例子
实现步骤
1、新建 student 表
2、加入 maven 的 mybatis 坐标,mysql 驱动的坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.an</groupId>
<artifactId>LearnMybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- batis 依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
</dependencies>
<build>
</build>
</project>
3、创建实体类,Student - 保存表中的一行数据
package com.an.domain;
/**
* @author an
* @create 2021-05-29-15:02
*/
// 推荐和表名一样,容易记忆
public class Student {
// 定义属性,目前要求是属性名和列名保持一直
private Integer id;
private String name;
private String email;
private Integer age;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Integer getAge() {
return age;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
4、创建持久层的 dao 接口,定义操作数据库的方法
package com.an.dao;
import com.an.domain.Student;
import java.util.List;
/**
* @author an
* @create 2021-05-29-15:06
*/
// 接口操作 student 表
public interface StudentDao {
// 查询 student 表中的所有数据
public List<Student> selectStudent();
}
5、创建一个 mybatis 使用的配置文件,叫做 sql 映射文件
叫做 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="com.an.dao.StudentDao">
<!--
select:表示查询操作
id: 你要执行的 sql 语法的唯一标识,mybatis 会使用这个 id 的值来找到要执行的 sql 语句
可以自定义,但是要求你使用接口中的方法名称
resultType: 表示结果类型,是 sql 语句执行后得到的 ResultSet,遍历这个 ResultSet 得到 java
对象的类型,值为类型的全限定名称
-->
<select id="selectStudents" resultType="com.an.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">
2、约束文件作用:限制和检查在当前文件中出现的标签,必须符合 Mybatis 的要求
3、mapper 是当前文件的根标签,必须的
namespace: 叫做命名空间,唯一值的,可以是自定义的字符串,要求你使用 dao 接口的全限定名称
4、在当前文件中,可以使用特定标签来表示数据库的特定操作
<select>: 表示查询
<update>: 表示更新数据库的操作,在 update 标签中写的是 update sql 语句
<insert>: 表示插入
<delete>: 表示删除
-->
6、创建 mybatis 的主配置文件
一个项目就一个主配置文件
主配置文件提供了数据库的连接信息和sql映射文件的位置信息
在 main/resources 目录下创建
为了能够在target中出现 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>
mybatis.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>
<!-- 环境配置 数据库的连接信息
default: 必须和某个 environment 的 id 值一样
告诉 mybatis 使用哪个数据库的连接信息-->
<environments default="mydev">
<!-- environment: 一个数据库信息的配置,环境
id:一个唯一值,自定义,表示环境的名称
-->
<environment id="mydev">
<!--
transactionManager: mybatis 事务的类型
type: JDBC(表示使用 jdbc 中的 Connection 对象的 commit,rollback 的事务处理
-->
<transactionManager type="JDBC"/>
<!--
dataSource: 表示数据源,连接数据库的
type: 表示数据源的类型,POOLED 表示使用连接池
-->
<dataSource type="POOLED">
<!--
driver,user,username,password 是固定的,不能自定义
-->
<!-- 数据库的驱动类ming -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的 url 字符串 -->
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<!-- 访问数据库的用户名 -->
<property name="username" value="root"/>
<!-- 密码 -->
<property name="password" value="2232116722ca"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql 映射文件的位置) -->
<mappers>
<!-- 一个 mapper 标签指定一个文件的位置
从类路径开始的路径信息。target/classes(类路径)
-->
<mapper resource="com/an/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">
2、configuration 根标签
-->
7、创建使用 mybatis 类
通过 mybatis 访问数据库
package com.an;
import com.an.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;
/**
* @author an
* @create 2021-05-29-16:11
*/
public class MyApp {
public static void main(String[] args) throws IOException {
// 访问 mybatis 读取 student 数据
// 1 定义 mybatis 的主配置文件的名称,从类路径根开始
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 = factory.openSession();
// 6 [重要]指定要执行的 sql 语句的标识,sql 映射文件中的 namespace + "." + 标签的 id 值
String sqlId = "com.an.dao.StudentDao" + "." + "selectStudents";
// 7 执行 sql 语句,通过 sqlID 找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
// 8 输出结果
studentList.forEach(stu -> System.out.println(stu));
// 9 关闭 sqlSession 对象
sqlSession.close();
}
}
插入操作
接口 StudentDao.java
package com.an.dao;
import com.an.domain.Student;
import java.util.List;
/**
* @author an
* @create 2021-05-29-15:06
*/
// 接口操作 student 表
public interface StudentDao {
// 查询 student 表中的所有数据
public List<Student> selectStudents();
// 插入方法
// 参数: student,表示要插入的数据库数据
// 返回值:int,表示执行 insert 操作后的影响数据库的行数
public int insertStudent(Student student);
}
配置文件 StudentDao.xml
<mapper namespace="com.an.dao.StudentDao">
<!--
select:表示查询操作
id: 你要执行的 sql 语法的唯一标识,mybatis 会使用这个 id 的值来找到要执行的 sql 语句
可以自定义,但是要求你使用接口中的方法名称
resultType: 表示结果类型,是 sql 语句执行后得到的 ResultSet,遍历这个 ResultSet 得到 java
对象的类型,值为类型的全限定名称
-->
<select id="selectStudents" resultType="com.an.domain.Student">
select id,name,email,age from student order by id
</select>
<!-- 插入操作 -->
<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
测试代码
package com.an;
import com.an.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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author an
* @create 2021-05-29-16:49
*/
public class TestBatis {
// 测试方法,测试功能
@Test
public void test() throws IOException {
// 访问 mybatis 读取 student 数据
// 1 定义 mybatis 的主配置文件的名称,从类路径根开始
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 = factory.openSession();
// 6 [重要]指定要执行的 sql 语句的标识,sql 映射文件中的 namespace + "." + 标签的 id 值
String sqlId = "com.an.dao.StudentDao" + "." + "insertStudent";
// 7 执行 sql 语句,通过 sqlID 找到语句
Student stu = new Student(1003,"王五","ww@qq.com",23);
// mybatis 默认没有提交事务,所以在 insert,update,delete 后要手动提交事务
int nums = sqlSession.insert(sqlId,stu);
sqlSession.commit();
// 8 输出结果
System.out.println("执行insert的结果:"+nums);
// 9 关闭 sqlSession 对象
sqlSession.close();
}
}
配置日志功能
mybatis.xml 加入日志配置,可以在控制台输出执行的 sql 语句和参数
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
主要类的介绍
1、Resources: mybatis 中的一个类,负责读取主配置文件
InputStream in = Resources.getResourceAsStream(config);
2、SqlSessionFactoryBuilder: 创建 SqlSessionFactory 对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
3、SqlSessionFactory: 重量级对象,程序创建一个对象耗时比较长,使用资源比较多
在整个项目中,有一个就够了
SqlSessionFactory,接口实现类:DefaultSqlSessionFactory
作用,获取 SqlSession 对象
openSession()方法说明:
(1) openSession():无参数,获取的是非自动提交事务的 SqlSession 对象
(2) openSession(boolean):openSession(true) 获取自动提交事务的 SqlSession
4、SqlSession 接口
定义了操作数据的方法,例如 selectOne(),selectList(),insert(),update(),delete(),commit(),rollback()。
SqlSession 接口的实现类 DefaultSqlSession
SqlSession 对象不是线程安全的,需要在方法内部使用,在执行 sql 语句之前,使用 openSession 获取 SqlSession 对象,执行完语句后,需要关闭它,执行SqlSession.close(),保证它是线程安全的。
工具类
package com.an.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;
import java.io.InputStream;
/**
* @author an
* @create 2021-05-29-17:21
*/
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
String config = "mybatis.xml"; // 需要和你项目文件名一致
try {
InputStream in = Resources.getResourceAsStream(config);
// 创建 SqlSessionFactory 对象,使用 SqlSessionFactoryBuild
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取 SqlSession 的方法
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
if(factory!=null) {
sqlSession = factory.openSession();
}
return sqlSession;
}
}
使用工具类后
public class MyApp2 {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 6 [重要]指定要执行的 sql 语句的标识,sql 映射文件中的 namespace + "." + 标签的 id 值
String sqlId = "com.an.dao.StudentDao" + "." + "selectStudents";
// 7 执行 sql 语句,通过 sqlID 找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
// 8 输出结果
studentList.forEach(stu -> System.out.println(stu));
// 9 关闭 sqlSession 对象
sqlSession.close();
}
}