Mybatis

Posted g0rez

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis相关的知识,希望对你有一定的参考价值。

第1章 框架概述

1.1 软件开发常用结构

1.1.1 三层架构

三层架构包含的三层:
界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)

三层的职责

  1. 界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和
    用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。
  2. 业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
  3. 数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交
    给业务层,同时将业务层处理的数据保存到数据库.

三层的处理请求的交互:
用户---> 界面层--->业务逻辑层--->数据访问层--->DB 数据库
如图:

为什么要使用三层?

  1. 结构清晰、耦合度低, 各层分工明确,
  2. 可维护性高 可扩展性高
  3. 有利于标准化
  4. 开发人员可以只关注整个结构中的其中某一层的功能实现
  5. 有利于各层逻辑的复用

1.1.2 常用框架

常见的 J2EE 中开发框架:

MyBatis 框架:
MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句
本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。
MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java
对象并返回。

Spring 框架:

​ Spring 框架为了解决软件开发的复杂性而创建的。Spring 使用的是基本的 JavaBean 来完成以前
非常复杂的企业级开发。Spring 解决了业务对象,功能模块之间的耦合,不仅在 javase,web 中使用,
大部分 Java 应用都可以从 Spring 中受益。
​ Spring 是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。

SpringMVC 框架
Spring MVC 属于 SpringFrameWork 3.0 版本加入的一个模块,为 Spring 框架提供了构建 Web
应用程序的能力。现在可以 Spring 框架提供的 SpringMVC 模块实现 web 应用开发,在 web 项目中
可以无缝使用 Spring 和 Spring MVC 框架。

1.2 框架是什么

1.2.1 框架定义

​ 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方
法;另一种认为,框架是可被应用开发者定制的应用骨架、模板。
​ 简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。从另一个角度来
说框架一个舞台,你在舞台上做表演。在框架基础上加入你要完成的功能。
​ 框架安全的,可复用的,不断升级的软件。

1.2.2 框架解决的问题

​ 框架要解决的最重要的一个问题是技术整合,在 J2EE 的 框架中,有着各种各样的技术,不同的应
用,系统使用不同的技术解决问题。需要从 J2EE 中选择不同的技术,而技术自身的复杂性,有导致更
大的风险。企业在开发软件项目时,主要目的是解决业务问题。 即要求企业负责技术本身,又要求解
决业务问题。这是大多数企业不能完成的。框架把相关的技术融合在一起,企业开发可以集中在业务领
域方面。
​ 另一个方面可以提供开发的效率。

1.3 JDBC 编程

1.3.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();
            }
        }
    }

1.3.2 用 使用 JDBC 的缺陷

  1. 代码比较多,开发效率低
  2. 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
  3. 对 ResultSet 查询的结果,需要自己封装为 List
  4. 重复的代码比较多些
  5. 业务代码和数据库的操作混在一起

1.4 MyBatis 框架概述

MyBatis 框架:
MyBatis 本是 apache 的一个开源项目 iBatis, 2010 年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis 。2013 年 11 月迁移到 Github。
iBATIS 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。iBATIS 提供的
持久层框架包括 SQL Maps 和 Data Access Objects(DAOs)
当前,最新版本是 MyBatis 3.5.1 ,其发布时间是 2019 年 4 月 8 日。

1.4.1 MyBatis 解决的主要问题

​ 减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。
直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳.

MyBatis 可以完成:

  1. 注册数据库的驱动,例如 Class.forName(“com.mysql.jdbc.Driver”))
  2. 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
  3. 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象
List<Student> list = new ArrayLsit<>();
ResultSet rs = state.executeQuery(“select * from student”);
while(rs.next){
	Student student = new Student();
	student.setName(rs.getString(“name”));
	student.setAge(rs.getInt(“age”));
	list.add(student);
}

4.关闭资源ResultSet.close() , Statement.close() , Conenection.close()

第2章 MyBatis 框架快速入门

内容列表:
◼ 快速开始一个 MyBatis
◼ 基本 CURD 的操作
◼ MyBatis 内部对象分析
◼ 使用 Dao 对象

2.1 入门案例

MyBatis 开发准备
搭建 MyBatis 开发环境,实现第一个案例

2.1.1 使用 Mybatis 准备

下载 mybatishttps://github.com/mybatis/mybatis-3/releases

2.1.2 搭建 MyBatis 开发环境

1. 创建 mysql 数据库和表

数据库名 ssm ;表名 student

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;

2. 创建 maven 工程

创建 maven 工程,信息如下:
模板:

工程坐标:

3. 删除默认创建的 App 类文件

4. 加入 maven 坐标

pom.xml 加入 maven 坐标:

<dependencies>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
</dependency>
</dependencies>

5. 加入 maven 插件

<build>
<resources>
    <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
    </resource>
</resources>
<plugins>
    <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>
</build>

6. 编写 Student 实体类

创建包 com.g0rez.domain, 包中创建 Student 类

package com.g0rez.domain;
/**
 * <p>Description: 实体类 </p>
 */
public class Student {
    // 属性名和列名一样
    private Integer id;
    private String name;
    private String email;
    private Integer age;
// set ,get , toString
}

7.编写 Dao接口StudentDao

创建 com.g0rez.dao 包,创建 StudentDao 接口

package com.g0rez.dao;
import com.g0rez.domain.Student;
import java.util.List;
/*
 * <p>Description: Dao 接口 </p>
 */
public interface StudentDao {
    /* 查询所有数据*/
    List<Student> selectStudents();
}

8.编写Dao接口Mapper映射文件StudentDao.xml

要求:

  1. 在 dao 包中创建文件 StudentDao.xml
  2. 要 StudentDao.xml 文件名称和接口 StudentDao 一样,区分大小写的一样。
<?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">
        <!--
        namespace :必须有值,自定义的唯一字符串
        推荐使用: dao 接口的全限定名称
        -->
<mapper namespace="com.g0rez.dao.StudentDao">
<!--
<select>: 查询数据, 标签中必须是 select 语句
id: sql 语句的自定义名称,推荐使用 dao 接口中方法名称,
使用名称表示要执行的 sql 语句
resultType: 查询语句的返回结果数据类型,使用全限定类名
-->
<select id="selectStudents" resultType="com.g0rez.domain.Student">
    <!-- 要执行的 sql 语句 -->
    select id,name,email,age from student
</select>
</mapper>

9.创建MyBatis主配置文件

项目 src/main 下创建 resources 目录,设置 resources 目录为 resources root
创建主配置文件:名称为 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>
<!-- 配置 mybatis 环境 -->
<environments default="mysql">
    <!--id: 数据源的名称 -->
    <environment id="mysql">
        <!-- 配置事务类型:使用 JDBC 事务(使用 Connection 的提交和回滚) -->
        <transactionManager type="JDBC"/>
        <!-- 数据源 dataSource :创建数据库 Connection 对象
        type: POOLED 使用数据库的连接池
        -->
        <dataSource type="POOLED">
            <!-- 连接数据库的四个要素 -->
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </dataSource>
    </environment>
</environments>
<mappers>
    <!-- 告诉 mybatis 要执行的 sql 语句的位置 -->
    <mapper resource="com/g0rez/dao/StudentDao.xml"/>
</mappers>
</configuration>

10.创建测试类MyBatisTest

src/test/java/com/g0rez/ 创建 MyBatisTest.java 文件

/*
 * mybatis 入门
 */
    @Test
    public void testStart() throws IOException {
		//1.mybatis 主配置文件
        String config = "mybatis-config.xml";
		//2. 读取配置文件
        InputStream in = Resources.getResourceAsStream(config);
		//3. 创建 SqlSessionFactory 对象, , 目的是获取 Sql Session
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
		//4. 获取 SqlSession,SqlSession 能执行 sql 语句
        SqlSession session = factory.openSession();
		//5. 执行 SqlSession 的 selectList()
        List<Student> studentList =
        session.selectList("com.g0rez.dao.StudentDao.selectStudents");
		//6. 循环输出查询结果
        studentList.forEach( student -> System.out.println(student));
		//7. 关闭 SqlSession ,释放资源
        session.close();
    }
List<Student> studentList =
session.selectList("com.g0rez.dao.StudentDao.selectStudents");
//近似等价的 jdbc 代码
Connection conn = 获取连接对象
String sql=” select id,name,email,age from student”
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();

11.配置日志功能

mybatis.xml 文件加入日志配置,可以在控制台输出执行的 sql 语句和参数

<settings>
	<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

2.2 基本的 CURD

查询一个用selectOne

insert ,update ,delete

2.2.1 insert

1.StudentDao 接口中增加方法

int insertStudent(Student student);

2.StudentDao.xml 加入sql 语句

<insert id="insertStudent">
	insert into student(id,name,email,age)
	values(#{id},#{name},#{email},#{age})
</insert>

3.增加测试方法

@Test
    public void testInsert() throws IOException {
		//1.mybatis 主配置文件
        String config = "mybatis-config.xml";
		//2. 读取配置文件
        InputStream in = Resources.getResourceAsStream(config);
		//3. 创建 SqlSessionFactory 对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
		//4. 获取 SqlSession
        SqlSession session = factory.openSession();
		//5. 创建保存数据的对象
        Student student = new Student();
        student.setId(1005);
        student.setName(" 张丽");
        student.setEmail("zhangli@163.com");
        student.setAge(20);
		//6. 执行插入 insert
        int rows = session.insert(
                "com.g0rez.dao.StudentDao.insertStudent",student);
		//7. 提交事务
        session.commit();
        System.out.println(" 增加记录的行数:"+rows);
		//8. 关闭 SqlSession
        session.close();
    }

2.2.2 update

1.StudentDao 接口中增加方法

int updateStudent(Student student);

2.StudentDao.xml 增加 sql 语句

<update id="updateStudent">
	update student set age = #{age} where id=#{id}
</update>

3.增加测试方法

@Test
    public void testUpdate() throws IOException {
		//1.mybatis 主配置文件
        String config = "mybatis-config.xml";
		//2. 读取配置文件
        InputStream in = Resources.getResourceAsStream(config);
		//3. 创建 SqlSessionFactory 对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
		//4. 获取 SqlSession
        SqlSession session = factory.openSession();
		//5. 创建保存数据的对象
        Student student = new Student();
        student.setId(1005);// 要修改的 id
        student.setAge(30); // 要修改的年龄值
		//6. 执行 更新 update
        int rows = session.update(
                "com.g0rez.dao.StudentDao.updateStudent",student);
		//7. 提交事务
        session.commit();
        System.out.println(" 修改记录的行数:"+rows);
		//8. 关闭 SqlSession
        session.close();
     
    }

2.2.3 delete

1.StudentDao 接口中增加方法

int deleteStudent(int id);

2.StudentDao.xml增加sql语句

<delete id="deleteStudent">
	delete from student where id=#{studentId}
</delete>

3.增加测试方法

@Test
    public void testDelete() throws IOException {
		//1.mybatis 主配置文件
        String config = "mybatis-config.xml";
		//2. 读取配置文件
        InputStream in = Resources.getResourceAsStream(config);
		//3. 创建 SqlSessionFactory 对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
		//4. 获取 SqlSession
        SqlSession session = factory.openSession();
		//5. 删除的 id
        int id = 1001;
		//6. 执行删除 delete
        int rows = session.delete(
                "com.g0rez.dao.StudentDao.deleteStudent",id);
		//7. 提交事务
        session.commit();
        System.out.println(" 修改记录的行数:"+rows);
		//8. 关闭 SqlSession
        session.close();
    }

2.3 MyBatis 对象分析

2.3.1 对象使用

SqlSession , SqlSessionFactory 等

1.Resources类

Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返
回不同类型的 IO 流对象。

2.SqlSessionFactoryBuilder类

SqlSessionFactory 的 创 建 , 需 要 使 用 SqlSessionFactoryBuilder 对 象 的 build() 方 法 。 由 于
SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将
该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。

3.SqlSessionFactory接口

SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用
只需要一个该对象即可。创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。

openSession(true):创建一个有自动提交功能的 SqlSession
openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交
openSession():同 openSession(false)

4.SqlSession接口

SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以
SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。
SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将
其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。

2.3.2 创建工具类

1.创建 MyBatisUtil 类

package com.g0rez.common;

/**
 * <p>Description: 实体类 </p>
 */
public class MyBatisUtil {
    // 定义 SqlSessionFactory
    private static SqlSessionFactory factory = null;
    static {
		// 使用 静态块 创建一次 SqlSessionFactory
        try{
            String config = "mybatis-config.xml";
		// 读取配置文件
            InputStream in = Resources.getResourceAsStream(config);
		// 创建 SqlSessionFactory 对象
            factory = new SqlSessionFactoryBuilder().build(in);
        }catch (Exception e){
            factory = null;
            e.printStackTrace();
        }
    }
    /* 获取 SqlSession 对象 */
    public static SqlSession getSqlSession(){
        SqlSession session = null;
        if( factory != null){
            session = factory.openSession();
        }
        return session;
    }
}

2.使用MyBatisUtil类

@Test
    public void testUtils() throws IOException {
        SqlSession session = MyBatisUtil.getSqlSession();
        List<Student> studentList = session.selectList(
                "com.g0rez.dao.StudentDao.selectStudents");
        studentList.forEach( student -> System.out.println(student));
        session.close();
    }

以上是关于Mybatis的主要内容,如果未能解决你的问题,请参考以下文章

SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper

mybatis动态sql片段与分页,排序,传参的使用

MyBatis动态SQL标签用法

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

mybatis动态sql之利用sql标签抽取可重用的sql片段

[mybatis]动态sql_sql_抽取可重用的sql片段