Skip to content

MyBatis

mybatis

简介

MyBatis是一种Java持久化框架,它可以将SQL语句和Java对象之间的映射关系定义在XML文件或注解中,从而简化了数据库操作的编写和维护。MyBatis提供了丰富的功能,包括动态SQL、缓存、批处理等,可以帮助开发者更加高效地进行数据库操作。

使用方式

  • 独立使用

    • 配置繁琐
  • 与Spring或Spring Boot结合

    • 命名约定

    • 注解


生命周期

procedure


核心接口和类的结构

classes


Spring Boot集成

安装

pom.xml添加以下依赖:

1
2
3
4
5
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>3.0.1</version>
</dependency>

开发流程

mybatis-spring-boot-starter是一个用于在Spring Boot应用中集成MyBatis的starter,使用它可以方便地进行MyBatis的配置和使用。下面是mybatis-spring-boot-starter的开发流程:

在pom.xml文件中添加MyBatis和MyBatis-Spring的依赖。

1
2
3
4
5
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.4</version>
</dependency>

在application.properties文件中配置数据源信息。

# 配置数据源
spring.datasource.url=jdbc:sqlite:c:/app/sqlite/data-dev.db
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.sql.init.schema-locations = classpath:sql/stu_schema.sql
spring.sql.init.data-locations = classpath:sql/stu_data.sql
spring.sql.init.mode=embedded

#mybatis
mybatis.type-aliases-package=xust.stu.**.domain
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.typeAliasesPackage=xust.stu.**.domain

在应用程序入口增加扫描配置

1
2
3
4
5
6
7
8
9
@RestController
@EnableTransactionManagement
@MapperScan("com.example.demo.*")
@SpringBootApplication
public class StuApplication {
    public static void main(String[] args) {
        SpringApplication.run(StuApplication.class, args);
    }
}

按Java Bean规范创Student类。

1
2
3
public class Student{
  private String id;
}
源代码
/*
 * File name : Student.java 2023-04-20
 * @generated May 17, 2023, 1:13:27 PM
 * @author XUST
 * Copyright 2023 XUST. All rights reserved.
 */
package xust.stu.demo.domain;

import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
//import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
//import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


/**
 * Class Student
 * 学生表
 * @author XUST
 * @version 1.0, 2023-04-20
 */
public class Student{
  private static final long serialVersionUID = -8178158848305435288L;
  public static ObjectMapper objectMapper = new ObjectMapper();


  /**
   * Id
   */
  private String id;

  /**
   * 学号
   */
  @NotNull
  private String no;

  /**
   * 姓名
   */
  private String name;

  /**
   * 性别
   */
  private String gender;

  /**
   * 年龄
   */
  private Integer age;

  /**
   * 所在系
   */
  private String dept;


    /**
     * Id
     */
    public String getId(){
        return id;
    }

    /**
     * Id
     */
    public void setId(String newValue){
        id = newValue;
    }
    /**
     * 学号
     */
    public String getNo(){
        return no;
    }

    /**
     * 学号
     */
    public void setNo(String newValue){
        no = newValue;
    }
    /**
     * 姓名
     */
    public String getName(){
        return name;
    }

    /**
     * 姓名
     */
    public void setName(String newValue){
        name = newValue;
    }
    /**
     * 性别
     */
    public String getGender(){
        return gender;
    }

    /**
     * 性别
     */
    public void setGender(String newValue){
        gender = newValue;
    }
    /**
     * 年龄
     */
    public Integer getAge(){
        return age;
    }

    /**
     * 年龄
     */
    public void setAge(Integer newValue){
        age = newValue;
    }
    /**
     * 所在系
     */
    public String getDept(){
        return dept;
    }

    /**
     * 所在系
     */
    public void setDept(String newValue){
        dept = newValue;
    }

  @Override
  public String toString() {
    String res = "";

    try {
      res = objectMapper.writeValueAsString(this);
    } catch (Exception e) {
    }  

    return res;
  }
}

创建一个Mapper接口,定义SQL语句的方法。

1
2
3
public interface StudentMapper {
  Student getStudentById(int id);
}

在resources目录下创建一个Mapper XML文件,编写SQL语句。

1
2
3
4
5
<mapper namespace="com.example.demo.mapper.StudentMapper">
  <select id="getStudentById" resultType="com.example.demo.entity.Student">
      select * from Student where id = #{id}
  </select>
</mapper>

在需要使用Mapper接口的地方注入Mapper接口,调用Mapper接口中的方法即可。

@RestController
public class StudentController {
    @Autowired
    private StudentMapper studentMapper;

    @GetMapping("/student/{id}")
    public Student getStudentById(@PathVariable int id) {
        return studentDao.getStudentById(id);
    }
}

配置

Spring Boot数据源配置

以下是Spring Boot中常用的数据库配置参数及其描述和默认值:

参数名 描述 默认值
spring.datasource.url 数据库连接URL
spring.datasource.username 数据库用户名
spring.datasource.password 数据库密码
spring.datasource.driver-class-name 数据库驱动类名
spring.datasource.type 数据库连接池类型
spring.datasource.hikari.* HikariCP连接池配置
spring.datasource.tomcat.* Tomcat连接池配置
spring.datasource.dbcp2.* DBCP2连接池配置
spring.datasource.jndi-name JNDI数据源名称

其中,spring.datasource.url、spring.datasource.username、spring.datasource.password和spring.datasource.driver-class-name是必须配置的参数,其他参数根据需要进行配置。具体的配置方式可以参考Spring Boot官方文档。


Mybatis配置

mybatis-spring-boot-starter的配置参数如下:

参数名 描述 默认值
mybatis.config-location MyBatis配置文件的位置 classpath:mybatis-config.xml
mybatis.mapper-locations Mapper映射文件的位置,可以使用通配符 classpath:mapper/*/.xml
mybatis.type-aliases-package 实体类所在的包名,可以使用通配符 (无)
mybatis.type-handlers-package TypeHandler所在的包名,可以使用通配符 (无)
mybatis.configuration.properties MyBatis配置属性 (无)
mybatis.configuration.map-underscore-to-camel-case 是否开启驼峰命名转换 false
mybatis.configuration.cache-enabled 是否开启缓存 true
mybatis.configuration.lazy-loading-enabled 是否开启延迟加载 false
mybatis.configuration.default-statement-timeout SQL执行超时时间,单位为秒 (无)
mybatis.configuration.default-fetch-size 每次查询返回的记录数 (无)
mybatis.configuration.default-statement-type SQL执行方式,可选值为STATEMENT、PREPARED、CALLABLE PREPARED
mybatis.configuration.default-executor-type 执行器类型,可选值为SIMPLE、REUSE、BATCH SIMPLE
mybatis.configuration.jdbc-type-for-null 当Java类型为null时,对应的JDBC类型 OTHER
mybatis.configuration.log-impl 日志实现类 org.apache.ibatis.logging.stdout.StdOutImpl

SQL映射文件

1
2
3
4
5
6
7
<?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="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

SQL 映射文件结构

元素 功能
cache 配置给定命名空间的缓存。
cache-ref 从其他命名空间引用缓存配置。
resultMap 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载对象。
sql 可以重用的 SQL 块,也可以被其他语句引用。
insert 映射插入语句
update 映射更新语句
delete 映射删除语句
select – 映射查询语句

Select

<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" parameterType="int" resultType="Blog"> 
    select * from Blog where id = #{id} 
  </select>
</mapper>

<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog2" parameterType="int" resultType="map"> 
    select * from Blog where id = #{id} 
  </select>
</mapper>

使用完全限定名调用映射语句

1
2
3
4
5
6
7
Blog blog = (Blog) session.selectOne( 
  "org.mybatis.example.BlogMapper.selectBlog", 101);
String blogName=blog.getBlogName();

Map map = (Map) session.selectOne( 
  "org.mybatis.example.BlogMapper.selectBlog", 101);
String blogName=Map.get(BLOG_NAME);

Insert

1
2
3
<insert id="insertAuthor" parameterType="domain.blog.Author"> 
  insert into Author (id,username,password,email,bio) values (#{id},#{username},#{password},#{email},#{bio})
</insert>

主键策略

如果使用的数据库支持自动生成主键,那么就可以设置 useGeneratedKeys= ” true ” ,然后 把keyProperty 设成对应的列。

1
2
3
4
5
<insert id="insertAuthor" parameterType="domain.blog.Author" 
  useGeneratedKeys= "true" keyProperty= "id"> 
  insert into Author (username,password,email,bio) 
  values (#{username},#{password},#{email},#{bio}) 
</insert> 

Update

1
2
3
4
<update id="updateAuthor" parameterType="domain.blog.Author">
  update Author set username= #{username}, 
  password= #{password}, email= #{email}, bio= #{bio} where id= #{id}
</update> 

Delete

1
2
3
<delete id="deleteAuthor" parameterType="int"> 
  delete from Author where id = #{id} 
</delete>

动态SQL

MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力

  • if

  • choose(when,otherwise)

  • trim(where,set)

  • foreach


sql

这个元素用来定义一个可以复用的 SQL 语句段,供其它语句调用。比如:

1
2
3
4
5
6
7
<sql id="userColumns"> id,username,password</sql>
<!--这个语句块,可以包含到别的语句中,比如:-->
<select id="selectUsers " parameterType="int " resultType="hashmap ">
  select <include refid="userColumns " />
  from some_table
  where id = #{id}
</select>

if

<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog">
  SELECT * FROM BLOG WHERE state = "ACTIVE"
  <if test="title != null"> 
    AND title like #{title} 
  </if>
  <if test="author != null and author.name != null"> 
    AND title like #{author.name} 
  </if>
</select>

where

<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null"> 
      state = #{state} 
    </if>
    <if test="title != null"> 
      AND title like #{title} 
    </if>
  </where>
</select>