【SSM框架】MyBatis笔记 --- 三层架构;MyBatis框架结构;MyBatis 核心配置文件;sql 映射文件;MyBatis 使用初步(通过Maven添加依赖)
楔子:
一、三层架构:
1、三层架构包含的三层:
界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。
2、三层的职责:
界面层:接受用户的数据,调用业务逻辑层进行功能处理,返回结果给客户端,过去的 servlet 就是界面层的功能。
业务逻辑层:用来进行整个项目的业务逻辑处理,向上为界面层提供处理结果,向下问数据访问层要数据。
数据访问层:专门用来进行对数据的增、删、改、查操作,向上为业务逻辑层提供数据。
3、三层之间处理请求的交互:
(客户端)<--->界面层<--->业务逻辑层<--->数据访问层<--->(数据库)
各层之间的调用顺序是固定的,不允许跨层访问。
二、框架:
1、框架(Framework)是一个半成品软件,将所有的公共的,重复的功能解决掉,帮助程序快速高效的进行开发,它是可复用的,可拓展的。
2、常见的框架 --- SSM:
Spring:它是整合其它框架的框架,它的核心是IOC和AOP,它由20多个模块构成,在很多领域都提供了很好的解决方案。
SpringMVC:专门用来优化控制器(servlet),提供了极简单的数据提交,数据携带,页面跳转等功能。
MyBatis:是持久化层的一个框架,用来进行数据库访问的优化,专注于sql语句,极大的简化了JDBC的访问。
正文:
一、MyBatis 概述:
1、MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。
2、MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
3、MyBatis 解决的主要问题:
1)减轻使用 JDBC 的复杂性,不用编写,重复创建 Connetion , Statement ;
2)不用编写关闭资源代码;
3)直接使用 java 对象,表示结果数据;
二、MyBatis框架结构:
1、 mybatis配置文件:
【SqlMapConfig.xml】:此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
【mapper.xml】:文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
【SqlMapConfig.xml】:是mybatis的核心文件。mybatis将dao层与sql语句分离开来,虽然写的时候分离开来了,但是执行的时候还是要依靠sql语句,所以我们的sql语句写在Mapper.xml中。我们在加载核心的时候,会加载他下面的Mapper.xml,所以sql语句便会加载进去了。我们只需要在SqlMapConfig.xml中引入Mapper.xml就可以了,所以最后只需要加载SqlMapConfig.xml这一个核心配置文件。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂。工厂能帮我们去加载核心配置文件。加载了核心配置文件后就创建session,通过session可以对数据库进行操作。
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。Executor是执行者,我们不需要管,因为mybatis已经为我们封装好了。mybatis直接执行sql语句。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
8、Mapped Statement是输入与输出中间过程中产生的一些对象,通过这些对象去访问数据库。
总结:
工厂能帮我们去加载核心配置文件,同时创建会话,会话里面有执行者,执行sql语句,在执行sql语句的过程中产生对象,通过Mapped Statement封装成对象。执行sql语句就要需要输入参数和输出参数。
三、MyBatis 的使用:
1、添加框架的步骤:
1)添加依赖
2)添加配置文件
2、具体步骤:
1)新建库,新建表
2)新建Maven项目,勾选 Create from archetype,选择quickstart模板
3)修改目录:添加缺失的目录,修改目录属性
4)修改pom.xml文件:添加MyBatis的依赖,添加mysql的依赖
5)修改pom.xml文件:添加资源文件指定
6)在idea中添加数据库的可视化
7)添加jdbc.properties 属性文件(数据库的配置)
8)添加SqlMapConfig.xml文件,MyBatis的核心配置文件
9)创建实体类Student,用来封装数据
10)添加完成学生表的增删改查的功能的StudentMapper.xml 文件
11)创建测试类,进行功能测试
3、数据库预准备:
创建ssm库,建表student:
CREATE DATABASE ssm DEFAULT CHARSET utf8;
use ssm;
CREATE TABLE `student` (
`id` int(11) AUTO_INCREMENT primary key ,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into student(name,email,age) values('张三','zhangsan@126.com',22);
insert into student(name,email,age) values('李四','lisi@126.com',21);
insert into student(name,email,age) values('王五','wangwu@163.com',22);
insert into student(name,email,age) values('赵六','zhaoliun@qq.com',24);
四、MyBatis 对象分析:
1、 Resources 类:
Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。
2、SqlSessionFactoryBuilder 类
SqlSessionFactory 的创建 , 需要使用 SqlSessionFactoryBuilder 对象的 build() 方法 。 由于SqlSessionFactoryBuilder对象在创建完工厂对象后,就完成了其使命,即可被销毁。所以,一般会将该对象创建为一个方法内的局部对象,方法结束,对象销毁。
3、SqlSessionFactory 接口
SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用只需要一个该对象即可。创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。
1)openSession(true):创建一个有自动提交功能的SqlSession
2)openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
3)openSession():同 openSession(false)
4、SqlSession 接口
SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。
SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。
五、一堆栗子:
1、module 目录结构:
2、pom.xml:
<?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>org.burning</groupId>
<artifactId>mybatis_001_student</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--记得修改对应的JDK版本-->
<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>
<!--mybatis框架依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
<build>
<!--添加资源文件的指定(为了保证在源码中用到的各种配置文件,在编译之后,都顺利地到我tomcat指定的目录下)-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
3、jdbc.properties:
//这是博主的mysql配置信息,记得要修改为你的信息哟~
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=888
4、SqlMapConfig.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 下的子标签的顺序不能变-->
<configuration>
<!--读取属性文件(jdbc.properties)
属性(两种方式):
resource:从resource录下找指定名称的文件加载
url:使用绝对路径加载属性文件
例如:(记得把"\"改为“/”或者“\\”)
C:\java\mybatis\mybatis-course\mybatis_001_student\src\main\resources\jdbc.properties
-->
<properties resource="jdbc.properties"></properties>
<!--设置日志输出底层执行的代码-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--注册实体类的别名-->
<typeAliases>
<!-- <!–单个实体类别名的注册–>-->
<!-- <typeAlias type="org.burning.entity.Student" alias="student"></typeAlias>-->
<!--批量注册别名
别名是类名的驼峰命名法
-->
<package name="org.burning.entity"/>
</typeAliases>
<!--配置数据库的环境变量(数据库连接配置)
default:根据下面不同environment的id决定使用哪种数据库连接配置
-->
<environments default="development">
<!--开发时在公司时使用的配置-->
<environment id="development"><!--id:就是提供给environments的default属性使用-->
<!--配置事务管理器
type:指定事务管理的模式
JDBC:事务的控制交给程序员控制
MANAGED:由容器(spring)来管理事务
-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源
type:指定不同的配置方式
JNDI:java命名目录接口,在服务器端进行数据库连接池的管理
POOLED:使用数据库连接池
UNPOOLED:不使用数据库连接池
-->
<dataSource type="POOLED">
<!--配置数据库连接的基本参数
private String driver;
private String url;
private String username;
private String password;
-->
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<!--因为这里面都没有配内容,所以先将下面两个配置注释掉-->
<!--在家数据库的配置-->
<!-- <environment id="home">-->
<!-- <transactionManager type=""></transactionManager>-->
<!-- <dataSource type=""></dataSource>-->
<!-- </environment>-->
<!--上线后的数据库的配置-->
<!-- <environment id="online">-->
<!-- <transactionManager type=""></transactionManager>-->
<!-- <dataSource type=""></dataSource>-->
<!-- </environment>-->
</environments>
<!--注册mapper.xml
resource:从resources目录下找指定名称的文件加载
url:使用绝对路径加载属性文件
class:动态代理方式下的注册
-->
<mappers>
<mapper resource="StudentMapper.xml"></mapper>
</mappers>
</configuration>
5、Student.java:
package org.burning.entity;
public class Student {
private Integer id;
private String name;
private String email;
private Integer age;
public Student() {
}
public Student(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
public Student(Integer id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
6、StudentMapper.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:是整个文件的大标签,用来开始和结束xml文件
属性:
namespace:指定命名空间(相当于包名),用来区分不同mapper.xml文件中相同的id属性
-->
<mapper namespace="wgd">
<!--完成查询全部学生的功能
resultType:指定查询返回的结果集的类型,如果是集合,则必须是泛型的类型
parameterType:如果有参数,则通过它来指定参数的类型
-->
<select id="getAll" resultType="student">
select id,name,email,age
from student
</select>
<!--按主键id查询学生信息
-->
<select id="getById" parameterType="int" resultType="student">
select id,name,email,age
from student
where id=#{id}
</select>
<!--按学生名称模糊查询
判断使用 ${} 还是 #{} ?
如果要在字符串中使用,则用${},否则用 #{}
-->
<select id="getByName" parameterType="string" resultType="student">
select id,name,email,age
from student
where name like '%${name}%'
</select>
<!--增加学生-->
<insert id="insert" parameterType="student">
insert into student (name,email,age) value (#{name},#{email},#{age})
</insert>
<!--按主键删除学生-->
<delete id="deleteById" parameterType="int">
delete from student
where id=#{id}
</delete>
<!--按主键更新学生-->
<update id="updateById" parameterType="student">
update student set name=#{name},email=#{email},age=#{age}
where id=#{id}
</update>
</mapper>
7、Mytest.java:
package org.burning.test;
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.burning.entity.Student;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Mytest {
SqlSession sqlSession;
//在所有的@Test方法执行前先执行的代码
@Before
public void openSqlSession() throws IOException {
//使用文件流读取核心配置文件SqlMapConfig.xml
InputStream in = Resources.getResourceAsStream
("SqlMapConfig.xml");
//创建SqlSessionFactory工厂
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//取出SqlSession的对象
sqlSession = factory.openSession();
}
//在所有的@Test方法执行后执行的代码
@After
public void closeSqlSession() {
sqlSession.close();
}
@Test
public void testGetAll() throws IOException {
//完成查询操作
List<Student> list = sqlSession.selectList("wgd.getAll");
list.forEach(student -> System.out.println(student));
}
@Test
public void testGetById() throws IOException {
//按主键完成查询操作
Student student = sqlSession.selectOne("wgd.getById",2);
System.out.println(student);
}
@Test
public void testGetByName() throws IOException {
//按学生名称关键字完成查询操作
List<Student> studentList = sqlSession.selectList("wgd.getByName","杨");
studentList.forEach(student -> System.out.println(student));
}
@Test
public void testInsert() throws IOException {
//添加学生信息
int num = sqlSession.insert("wgd.insert",new Student("大爷","daye@126.com",50));
System.out.println(num);
//切记:在所有的增删改后,必须手动提交事务!
sqlSession.commit();
}
@Test
public void testDeleteById() throws IOException {
//按学生id完成删除操作
int num = sqlSession.delete("wgd.deleteById",21);
System.out.println(num);
//切记:在所有的增删改后,必须手动提交事务!
sqlSession.commit();
}
@Test
public void testUpdateById() throws IOException {
//按学生id完成更新操作
int num = sqlSession.update("wgd.updateById",new Student(20,"大爷","daye126@.com",500));
System.out.println(num);
//切记:在所有的增删改后,必须手动提交事务!
sqlSession.commit();
}
}
ps:
参考资料链接:mybatis框架的架构(图解) - wyhluckydog - 博客园 (cnblogs.com)