【3万字详解】一篇文章搞定Mybatis框架

文章目录

  • 前言
  • 第1章 框架概述
    • 1.1 软件开发常用结构
      • 1.1.1 三层架构
      • 1.1.2 常用框架
    • 1.2 框架是什么
      • 1.2.1 框架定义
      • 1.2.2 框架解决的问题
    • 1.3 JDBC编程
      • 1.3.1 JDBC编程的特点
      • 1.3.2 使用JDBC的缺陷
    • 1.4 Mybatis框架概述
      • 1.4.1 Mybatis主要解决的问题
  • 第2章 Mybatis框架快速入门
    • 2.1 入门案例
      • 2.1.1 搭建Mybatis开发环境
        • (1)创建mysql数据库和表
        • (2)导入Mybatis依赖
        • (3)解决Maven静态资源过滤问题
        • (4)编写Student实体类
        • (5)编写 Dao 接口 StudentDao
        • (6)编写 Dao 接口 Mapper 映射文件 StudentDao.xml
        • (7)创建 MyBatis 核心配置文件
        • (8)创建测试类 MybatisTest
        • (9)配置日志功能
    • 2.2 基本的CRUD(只演示insert)
      • 2.2.1 insert
        • (1)StudentDao 接口中增加方法
        • (2)StudentDao.xml 增加 sql 语句
        • (3)进行测试
    • 2.3 Mybatis主要类解析
      • 2.3.1 主要类介绍
        • (1)Resource 类
        • (2)SqlSessionFactoryBuilder 类
        • (3)SqlSessionFactory 接口
        • (4)SqlSession 接口
      • 2.3.2 创建工具类
        • (1)创建 MybatisUtil 类
        • (2)使用 MybatisUtil 类
  • 第3章 Mybatis 框架动态代理
    • 3.1 动态代理实现对数据库操作
      • 3.1.1 步骤
        • (1)getMapper 获取代理对象
        • (2)使用代理对象执行 sql 语句
    • 3.2 深入理解参数
      • 3.2.1 parameterType
      • 3.2.2 一个简单参数
      • 3.2.3 多个参数-使用@Param
      • 3.2.4 多个参数-使用对象
      • 3.2.5 #和$区别
    • 3.3 封装 Mybatis 输出结果
      • 3.3.1 resultType
        • (1)简单类型
        • (2)对象类型
        • (3)Map
      • 3.3.2 resultMap
      • 3.3.3 实体类属性名和列名不同的处理方式
        • (1)使用列别名和resultType
        • (2)使用resultMap
    • 3.4 模糊查询
  • 第4章 Mybatis 框架动态 SQL
    • 4.1 动态 SQL 简介
    • 4.2 动态 SQL 之 if
    • 4.3 动态 SQL 之 where
    • 4.4 动态 SQL 之 foreach
        • (1)遍历 List<简单类型>
        • (2)遍历 List<对象类型>
    • 4.5 动态 SQL 之 代码片段
  • 第5章 Mybatis 核心配置文件
    • 5.1 主配置文件
    • 5.2 dataSource 标签
      • 5.2.1 dataSource 类型
      • 5.2.2 dataSource 配置
    • 5.3 事务
        • (1)默认需要手动提交事务
        • (2)自动提交事务
    • 5.4 使用数据库属性配置文件
        • (1)在 classpath 路径下,创建 properties 文件
        • (2)使用 properties 标签
        • (3)使用 key 指定值
    • 5.5 typeAliases(类型别名)
    • 5.6 mappers(映射器)
        • (1)mapper resource=" "
        • (2)package name=" "
  • 第6章 PageHelper 分页插件
        • (1)maven 依赖
        • (2)加入 plugin 配置
        • (3)PageHelper 对象

前言

该技术博客是关于动力节点Mybatis教程的笔记总结,方便自己学习的同时希望能为大家带来帮助!

更多好文推荐

  • 【步骤详细】手把手整合Spring + Mybatis
  • Java常用类笔记
  • 计算机底层原理——汇编语言
  • 学习Java异常,吃透这篇足够

第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 常用框架

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编程的特点

我们在学习使用JDBC操作数据库时,发现JDBC操作太过繁琐,有许多重复性的代码,代码显得非常臃肿冗余,除了sql语句编写,其他操作基本上是大同小异,很影响开发效率

所以Mybatis框架的出现主要目的可以理解为:取代JDBC技术操作数据库!

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)

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 对象
  4. 关闭资源:ResultSet.close() , Statement.close() , Conenection.close()

第2章 Mybatis框架快速入门

2.1 入门案例

2.1.1 搭建Mybatis开发环境

(1)创建mysql数据库和表
# 创建数据库,名为ssm
create database ssm;

# 选中ssm数据库
use ssm;

# 在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)导入Mybatis依赖

创建maven项目后,在pom.xml中导入相关依赖:

<dependencies>
    
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
    dependency>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.1version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.9version>
    dependency>
dependencies>
(3)解决Maven静态资源过滤问题

在pom.xml中引入以下代码,否则没办法读取到Mapper映射文件:

<build>
    <resources>
        <resource>
            <directory>src/main/javadirectory>
            <includes>
                <include>**/*.propertiesinclude>
                <include>**/*.xmlinclude>
            includes>
            <filtering>falsefiltering>
        resource>
        <resource>
            <directory>src/main/resourcesdirectory>
            <includes>
                <include>**/*.propertiesinclude>
                <include>**/*.xmlinclude>
            includes>
            <filtering>falsefiltering>
        resource>
    resources>
build>
(4)编写Student实体类

创建包com.xu.pojo,在包中创建Student类:

package com.xu.pojo;

//推荐类名与数据库中的表名一致
public class Student {
    //定义属性,目前要求:属性名和列名一致
    private Integer id;
    private String name;
    private String email;
    private Integer age;
	//无参构造、有参构造、get、set、toString此处已省略
(5)编写 Dao 接口 StudentDao

创建com.xu.dao包,在包中创建StudentDao接口:

package com.xu.dao;

import com.xu.pojo.Student;
import java.util.List;

//接口操作student表
public interface StudentDao {
    //查询student表所有数据,表中每一行数据都能看做是一个student对象
    List<Student> selectStudents();
}
(6)编写 Dao 接口 Mapper 映射文件 StudentDao.xml
  1. 在 dao 包中创建映射文件 StudentDao.xml
  2. 使 StudentDao.xml 文件名和接口名 StudentDao 一样





<mapper namespace="com.xu.dao.StudentDao">
    
    <select id="selectStudents" resultType="com.xu.pojo.Student">
        
        select id,name,email,age from student order by id;
    select>
mapper>
(7)创建 MyBatis 核心配置文件

在resources目录下创建主配置文件:名为 mybatis-config.xml
说明:主配置文件名称是自定义的,内容如下:




<configuration>
    
    <environments default="mysql">
        
        <environment id="mysql">
            
            <transactionManager type="JDBC"/>
            
            <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>
        
        <mapper resource="com/xu/dao/StudentDao.xml"/>
    mappers>
configuration>

上述代码中mapper标签的注释图解,根据路径信息就可以找到并执行映射文件中的sql语句对数据库进行操作:
【3万字详解】一篇文章搞定Mybatis框架_第1张图片

(8)创建测试类 MybatisTest

在test.java包下创建测试类MybatisTest:

import com.xu.dao.StudentDao;
import com.xu.pojo.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 MybatisTest {
    public static void main(String[] args) throws IOException {
        //1.定义mybatis核心配置文件名,从类路径的根开始(target/classes)
        String config = "mybatis-config.xml";
        //2.读取mybatis核心配置文件
        InputStream is = Resources.getResourceAsStream(config);
        //3.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //5.【重要】获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //6.获取StudentDao接口的代理对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //7.执行接口代理对象中的方法
        List<Student> students = mapper.selectStudents();
        //8.输出结果
        for (Student student : students) {
            System.out.println(student);
        }
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

运行测试成功:
在这里插入图片描述

(9)配置日志功能

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

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

再次进行测试效果如下:
【3万字详解】一篇文章搞定Mybatis框架_第2张图片

2.2 基本的CRUD(只演示insert)

2.2.1 insert

(1)StudentDao 接口中增加方法
//添加学生操作,返回值int表示执行insert操作后,影响数据库的行数
//DML语句返回值都是int类型
int insertStudent(Student student);
(2)StudentDao.xml 增加 sql 语句
<insert id="insertStudent">
    insert into student values(#{id},#{name},#{email},#{age});
insert>
(3)进行测试
@Test
public void testInsert() throws IOException {
    //1.定义mybatis核心配置文件名,从类路径的根开始(target/classes)
    String config = "mybatis-config.xml";
    //2.读取mybatis核心配置文件
    InputStream is = Resources.getResourceAsStream(config);
    //3.创建SqlSessionFactoryBuilder对象
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    //4.创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(is);
    //5.【重要】获取SqlSession对象
    SqlSession sqlSession = factory.openSession();
    //6.获取StudentDao接口的代理对象
    StudentDao mapper = sqlSession.getMapper(StudentDao.class);
    //7.执行接口代理对象中的方法
    Student student = new Student(1003,"张飞","[email protected]",20);
    int nums = mapper.insertStudent(student);
    //8.【重要】mybatis默认不会自动提交事务,所以DML语句执行后需要手动提交事务
    sqlSession.commit();
    //9.输出insert语句影响数据的行数
    System.out.println(nums);
    //10.关闭SqlSession对象
    sqlSession.close();
}

这里我只展示insert操作,其他的delete、update操作我就不进行演示了,因为这些DML操作都是同理的,为了使该技术博客不那么冗余,这里就不做那么多重复演示了!

2.3 Mybatis主要类解析

2.3.1 主要类介绍

(1)Resource 类

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

//定义mybatis核心配置文件名,从类路径的根开始(target/classes)
String config = "mybatis-config.xml";
//读取mybatis核心配置文件
InputStream is = Resources.getResourceAsStream(config);
(2)SqlSessionFactoryBuilder 类

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

//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
(3)SqlSessionFactory 接口

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

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

//创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
//获取SqlSession对象
SqlSession sqlSession = factory.openSession();
(4)SqlSession 接口

SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。

SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。

SqlSession接口定义了操作数据的方法,例如 selectOne()、selectList()、insert()、update()、delete()、commit()、rollback(),SqlSession接口的实现类DefaultSqlSession。

使用要求:SqlSession对象是线程不安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行close(),这样能保证它的使用是线程安全的。

//关闭SqlSession对象
sqlSession.close();

2.3.2 创建工具类

(1)创建 MybatisUtil 类

在com.xu.util包下创建MybatisUtil类:

package com.xu.util;

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;

public class MybatisUtil {

    private static SqlSessionFactory factory = null;

    static {
        try {
            String config = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(config);
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取sqlSession的方法
    public static SqlSession getSqlSession() {
        SqlSession sqlSession = null;
        if (factory != null) {
            sqlSession = factory.openSession(); //非自动提交事务
        }
        return sqlSession;
    }
}
(2)使用 MybatisUtil 类
@Test
public void testInsert() throws IOException {
    //获取SqlSession对象
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    //获取StudentDao接口的代理对象
    StudentDao mapper = sqlSession.getMapper(StudentDao.class);
    //执行接口代理对象中的方法
    List<Student> students = mapper.selectStudents();
    //输出结果
    for (Student student : students) {
        System.out.println(student);
    }
    //关闭SqlSession对象
    sqlSession.close();
}

第3章 Mybatis 框架动态代理

3.1 动态代理实现对数据库操作

3.1.1 步骤

(1)getMapper 获取代理对象

MyBatis 框架抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。

Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。真正对数据库进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。

只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定接口实现类的 class 值。

(2)使用代理对象执行 sql 语句
@Test
public void testSelectStudents() {
    /**
     * 使用mybatis动态代理机制,使用sqlSession.getMapper(dao接口.class)
     * getMapper能获取dao接口对应的实现类对象
     */

    //1.获取SqlSession
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    //2.调用getMapper()获取到StudentDao接口的实现类对象
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    //3.调用接口实现类的方法,执行对数据库的操作
    List<Student> students = dao.selectStudents();
    //4.遍历输出结果
    for (Student student : students) {
        System.out.println(student);
    }
    //5.关闭SqlSession对象
    sqlSession.close();
}

3.2 深入理解参数

3.2.1 parameterType

parameterType: 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到 mapper 文件的 sql 语句。

mybatis通过反射机制能够得知接口参数的类型,所以一般情况下,我习惯不写parameterType

3.2.2 一个简单参数

Dao 接口中方法的参数只有一个简单类型(java 基本类型或 String类型),占位符 #{ 任意字符 },和方法的参数名无关

接口方法:

Student selectById(int id);

mapper映射文件:

<select id="selectById" resultType="com.xu.pojo.Student">
	select id,name,email,age from student where id = #{studentId}
select>

3.2.3 多个参数-使用@Param

当 Dao 接口方法多个参数,需要通过名称使用参数。在方法形参前面加入@Param(“自定义参数名”),mapper 文件使用#{自定义参数名}。

接口方法:

List<Student> selectMultiParam(@Param("personName") String name,
 							   @Param("personAge") int age);

mapper映射文件:

<select id="selectMultiParam" resultType="com.xu.pojo.Student">
 select id,name,email,age from student where name=#{personName} or age =#{personAge}
select>

3.2.4 多个参数-使用对象

使用 java 对象传递参数, java 的属性值就是 sql 需要的参数值。 每一个属性就是一个参数。语法格式: #{ property,javaType=java 中数据类型名,jdbcType=数据类型名称 }

由于javaType,jdbcType 的类型 MyBatis 可以检测出来,一般不需要设置。常用格式 #{ property }

创建保存参数值的对象:

public class QueryParam {
	private String queryName;
	private int queryAge;
	//set ,get 方法
}

接口方法:

List<Student> selectMultiObject(QueryParam queryParam);

mapper映射文件:

<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
	select id,name,email,age from student where name = #{queryName} or age = #{queryAge}
select>

3.2.5 #和$区别

#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的 “?”。这样做更安全,更迅速,#通常是首选做法

转化为 JDBC 的执行是:

String sql = "select id,name,email,age from student where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1005);

解释:
where id = ? 就是 where id = #{studentId}
ps.setInt(1,1005) , 1005 会替换掉 #{studentId}


$ :字符串替换,告诉 mybatis 使用$包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 ${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。


#和$区别:

  1. #使用 ?在sql语句中做占位,使用PreparedStatement执行sql,效率高
  2. #能够避免sql注入,更安全。
  3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  4. $有sql注入的风险,缺乏安全性。
  5. $:可以替换表名或者列名

3.3 封装 Mybatis 输出结果

3.3.1 resultType

resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用。

总而言之,resultType就是sql语句的执行结果转为java类型的对象!

【3万字详解】一篇文章搞定Mybatis框架_第3张图片

(1)简单类型

接口方法:

int countStudent();

mapper映射文件:

<select id="countStudent" resultType="int">
	select * from student;
select>
(2)对象类型

接口方法:

Student selectById(int id);

mapper映射文件:

<select id="selectById" resultType="com.xu.pojo.Student">
	select id,name,email,age from student where id=#{studentId}
select>

框架的处理: 使用构造方法创建对象。调用 setXXX 给属性赋值。
Student student = new Student();
【3万字详解】一篇文章搞定Mybatis框架_第4张图片

注意:Dao 接口方法返回是集合类型,需要指定集合中的类型,不是集合本身
【3万字详解】一篇文章搞定Mybatis框架_第5张图片

(3)Map

sql 的查询结果作为 Map 的 key 和 value。推荐使用 Map
注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录是错误

接口方法:

Map<Object,Object> selectReturnMap(int id);

mapper映射文件:

<select id="selectReturnMap" resultType="java.util.HashMap">
	select name,email from student where id = #{studentId}
select>

3.3.2 resultMap

resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况。

使用方式:

  1. 先定义 resultMap,指定列名和属性的对应关系。
  2. 在 select 中把 resultType 替换为 resultMap。

接口方法:

List<Student> selectAllStudents();

mapper映射文件:


<resultMap id="studentMap" type="com.xu.pojo.Student">
	
	<id column="id" property="id"/>
	
	<result column="name" property="name"/>
	<result column="email" property="email"/>
	<result column="age" property="age"/>
resultMap>


<select id="selectAllStudents" resultMap="studentMap">
	select id,name,email,age from student;
select>

3.3.3 实体类属性名和列名不同的处理方式

(1)使用列别名和resultType
  1. 创建一个新的实体类:
public class PrimaryStudent {
	private Integer stuId;
	private String stuName;
	private Integer stuAge;
	// set , get 方法
}
  1. mapper文件:

<select id="selectUseFieldAlias" resultType="com.xu.pojo.PrimaryStudent">
	select id as stuId, name as stuName,age as stuAge from student;
select>
(2)使用resultMap

mapper文件:


<resultMap id="primaryStudentMap" type="com.xu.pojo.PrimaryStudent">
	
	<id column="id" property="stuId" />
	
	<result column="name" property="stuName"/>
	<result column="age" property="stuAge" />
resultMap>


<select id="selectUseDiffResultMap" resultMap="primaryStudentMap">
	select id,name,email,age from student;
select>

3.4 模糊查询

模糊查询的实现有两种方式:

  1. java 代码中给查询数据加上“%” ;
  2. 在 mapper 文件 sql 语句的条件位置加上“%”

例1:java 代码中提供要查询的 “%力%”

接口方法:

List<Student> selectLikeFirst(String name);

mapper文件:

<select id="selectLikeFirst" resultType="com.xu.pojo.Student">
	select id,name,email,age from student where name like #{studentName}
select>

测试方法:

@Test
public void testSelectLikeOne(){
	String name="%力%";
	List<Student> stuList = studentDao.selectLikeFirst(name);
}

例2:mapper 文件中使用 like name “%” #{xxx} “%”

接口方法:

List<Student> selectLikeSecond(String name);

mapper文件:

<select id="selectLikeSecond" resultType="com.xu.pojo.Student">
	select id,name,email,age from student where name like "%" #{studentName} "%"
select>

测试方法:

@Test
public void testSelectLikeSecond(){
	String name="力";
	List<Student> stuList = studentDao.selectLikeSecond(name);
}

第4章 Mybatis 框架动态 SQL

4.1 动态 SQL 简介

动态 SQL,通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句。这里的条件判断使用的表达式为 OGNL 表达式。常用的动态 SQL 标签有 if、where、choose、foreach 等。

MyBatis 的动态 SQL 语句,与 JSTL 中的语句非常相似。

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的 SQL 语句。此时,可使用动态 SQL 来解决这样的问题

4.2 动态 SQL 之 if

对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。

<if test=”条件”>
	sql 语句内容
if>

接口方法:

//如果使用动态SQL,那么参数类型必须是java对象
List<Student> selectStudentIf(Student student);

mapper文件:

<select id="selectStudentIf" resultType="com.xu.pojo.Student">
	select id,name,email,age from student
	where 1=1
	<if test="name != null and name !='' ">
		and name = #{name}
	if>
	<if test="age > 0 ">
		and age > #{age}
	if>
select>

4.3 动态 SQL 之 where

if 标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后的所有 if 条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。

使用 where 标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。需要注意的是,第一个 if 标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它 if 中 SQL 片段的 and,必须要求写上。否则 SQL 语句将拼接出错。

<where>
	其他动态 sql 
where>

接口方法:

List<Student> selectStudentWhere(Student student);

mapper文件:

<select id="selectStudentWhere" resultType="com.xu.pojo.Student">
	select id,name,email,age from student
	<where>
		<if test="name != null and name !='' ">
			and name = #{name}
		if>
		<if test="age > 0 ">
			and age > #{age}
		if>
	where>
select>

4.4 动态 SQL 之 foreach

foreach 标签用于实现对于数组与集合的遍历。进行使用,需要注意:

➢ collection 表示要遍历的集合类型:list,array 等。
➢ open、close、separator 对遍历内容的 SQL 拼接。

<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
	#{item 的值}
foreach>
(1)遍历 List<简单类型>

表达式中的 List 使用 list 表示,其大小使用 list.size 表示。

需求:查询学生 id 是 1002,1005,1006

接口方法:

List<Student> selectStudentForList(List<Integer> idList);

mapper文件:

<select id="selectStudentForList" resultType="com.xu.pojo.Student">
	select id,name,email,age from student
	<if test="list !=null and list.size > 0 ">
		where id in
		<foreach collection="list" open="(" close=")" item="stuid" separator=",">
			#{stuid}
		foreach>
	if>
select>

测试方法:

@Test
public void testSelectForList() {
	List<Integer> list = new ArrayList<>();
	list.add(1002);
	list.add(1005);
	list.add(1006);
	List<Student> studentList = studentDao.selectStudentForList(list);
}
(2)遍历 List<对象类型>

接口方法:

List<Student> selectStudentForList2(List<Student> stuList);

mapper文件:

<select id="selectStudentForList2" resultType="com.xu.pojo.Student">
	select id,name,email,age from student
	<if test="list !=null and list.size > 0 ">
		where id in
		<foreach collection="list" open="(" close=")" item="stuobject" separator=",">
			#{stuobject.id}
		foreach>
	if>
select>

测试方法:

@Test
public void testSelectForList2() {
	List<Student> list = new ArrayList<>();
	Student s1 = new Student();
	s1.setId(1002);
	list.add(s1);
	
	s1 = new Student();
	s1.setId(1005);
	list.add(s1);
	
	List<Student> studentList = studentDao.selectStudentForList2(list);
}

4.5 动态 SQL 之 代码片段

sql 标签用于定义 SQL 片断,以便其它 SQL 标签复用。而其它标签使用该 SQL 片断,需要使用 include 子标签。该 sql 标签可以定义 SQL 语句中的任何部分,所以 include 子标签可以放在动态 SQL的任何位置。

接口方法:

List<Student> selectStudentSqlFragment(List<Student> stuList);

mapper文件:


<sql id="studentSql">
	select id,name,email,age from student
sql>
<select id="selectStudentSqlFragment" resultType="com.xu.pojo.Student">
	
	<include refid="studentSql"/>
	<if test="list !=null and list.size > 0 ">
		where id in
		<foreach collection="list" open="(" close=")" item="stuobject" separator=",">
			#{stuobject.id}
		foreach>
	if>
select>

第5章 Mybatis 核心配置文件

5.1 主配置文件

项目中使用的 mybatis-config.xml 是核心配置文件。

核心配置文件特点:

  1. xml 文件,需要在头部使用约束文件


  1. 根元素:configuration
  2. 核心配置文件主要包含内容:
    ➢ 定义别名
    ➢ 数据源
    ➢ mapper 文件

5.2 dataSource 标签

Mybatis 中访问数据库,可以连接池技术,但它采用的是自己的连接池技术。在 Mybatis 的 mybatis-config.xml 配置文件中,通过 dataSource type=”pooled” 来实现 Mybatis 中连接池的配置。dataSource可以理解为就是Connection对象

5.2.1 dataSource 类型

【3万字详解】一篇文章搞定Mybatis框架_第6张图片
上图看出 Mybatis 将数据源分为三类:

UNPOOLED:不使用连接池的数据源
POOLED:使用连接池的数据源
JNDI:使用JNDI实现的数据源

其中 UNPOOLED ,POOLED 数据源实现了 javax.sq.DataSource 接口, JNDI 和前面两个实现方式不同,了解可以。
【3万字详解】一篇文章搞定Mybatis框架_第7张图片

5.2.2 dataSource 配置

在 mybatis-config.xml 核心配置文件中配置 dataSource:

<dataSource type="POOLED">
	
	<property name="driver" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost:3306/ssm?charset=utf-8"/>
	<property name="username" value="root"/>
	<property name="password" value="root"/>
dataSource>

MyBatis 在初始化时,根据 dataSource 的 type 属性来创建相应类型的的数据源 DataSource,即:

type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED”:MyBatis会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

5.3 事务

(1)默认需要手动提交事务

Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback()

Connection 对象的 setAutoCommit()方法来设置事务提交方式:自动提交和手工提交

<transactionManager type="JDBC"/>

该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED

  • JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback()方法回滚。但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。从日志的输出信息中可以看到。
  • MANAGED:由容器来管理事务的整个生命周期(如 Spring 容器)。
(2)自动提交事务

设置自动提交的方式,factory 的 openSession() 分为有参数和无参数的。

SqlSession openSession();
SqlSession openSession(boolean autoCommit);

有参数为 true,使用自动提交,可以修改 MyBatisUtil 的 getSqlSession()方法。

session = factory.openSession(true);

再执行 insert 操作,无需执行 session.commit(),事务是自动提交的

5.4 使用数据库属性配置文件

为了方便对数据库连接的管理,DB 连接四要素数据一般都是存放在一个专门的属性文件中的。MyBatis主配置文件需要从这个属性文件中读取这些数据。步骤如下:

(1)在 classpath 路径下,创建 properties 文件

在 resources 目录创建 jdbc.properties 文件,文件名称自定义。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?charset=utf-8
jdbc.username=root
jdbc.password=root
(2)使用 properties 标签

修改主配置文件,文件开始位置加入:

<properties resource="jdbc.properties"/>
(3)使用 key 指定值
<dataSource type="POOLED">
    
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
dataSource>

5.5 typeAliases(类型别名)

Mybatis 支持默认别名,我们也可以采用自定义别名方式来开发,主要使用在 select resultType=”别名”

mybatis-config.xml 主配置文件定义别名:

<typeAliases>
	
	<typeAlias type="com.xu.pojo.Student" alias="mystudent"/>
	
	
	<package name="com.xu.pojo"/>
	<package name="其他包"/>
typeAliases>

mapper.xml 文件,使用别名表示类型:

<select id="selectStudents" resultType="mystudent">
	select id,name,email,age from student
select>

5.6 mappers(映射器)

(1)mapper resource=" "

使用相对于类路径的资源,从 classpath 路径查找文件:

<mapper resource="com/xu/dao/StudentDao.xml" /> 
(2)package name=" "

指定包下的所有 Dao 接口:

<package name="com.xu.dao"/> 

注意:此种方法要求 Dao 接口名称和 mapper 映射文件名称相同,且在同一个目录中。

第6章 PageHelper 分页插件

插件使用步骤如下:

(1)maven 依赖
<dependency>
	<groupId>com.github.pagehelpergroupId>
	<artifactId>pagehelperartifactId>
	<version>5.1.10version>
dependency>
(2)加入 plugin 配置

在 environments 之前加入

<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor" />
plugins>
(3)PageHelper 对象

查询语句之前调用 PageHelper.startPage 静态方法。

除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。
在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个 MyBatis 查询方法会被进行分页。

@Test
public void testSelect() throws IOException {
	//获取第 1 页,3 条内容
	PageHelper.startPage(1,3);
	List<Student> studentList = studentDao.selectStudents();
	studentList.forEach( stu -> System.out.println(stu));
}

你可能感兴趣的:(mybatis,mysql,数据库,jdbc,动态代理)