Mybatis

发布时间 2023-07-25 09:39:50作者: WCHAT

基础知识

什么是Mybatis

它是一款基于java的半自动ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低。

什么是ORM?

Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应。Student类就对应student表,一个Student对象就对应student表中的一行数据

为什么mybatis是半自动的ORM框架?

用mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。用hibernate开发,只需要定义好ORM映射关系,就可以直接进行CRUD操作了。由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。虽然mybatis需要手写SQL,但相比JDBC,它提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发的效率。并且它的学习成本也比hibernate低很多
特性

参数解析

$():表示一个拼接符号,仅仅为一个纯碎的string替换,在动态SQL解析阶段将会进行变量替换。

():表示一个占位符号,解析为一个JDBC预编译语句(prepared statement)的参数标记符,一个#{}被解析为一个参数占位符。

Mybatis执行流程

图示流程

详细流程

(1)读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。

(2)加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

(3)构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。

(4)创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。

(5)Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

(6)MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。

(7)输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。

(8)输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。

Mybatis开发Dao层

开发方式

传统开发方式

需要创建Dao层Mapper接口和其实现类,再手动创建其实现类对象进行方法调用

接口代理开发方式(主流)

仅需编写Dao层Mapper接口,由Mybatis的mapper代理自动创建接口的实现类,最后由mapper代理对象调用方法

Mapper接口代理开发需要遵循以下规范

映射配置文件中的namespace与mapper接口的类名相同
映射配置文件中的增删改查标签的id属性要和Mappe接口中的方法名相同
映射配置文件中的增删改查标签的parameterType属性要和Mappe接口中的方法参数相同
映射配置文件中的增删改查标签的resultType属性要和Mappe接口中方法的返回值相同

示例

UserMapperProxy.java

public interface UserMapperProxy {

    public List<User> getAllUser();
}

UserMapperProxy.xml

<mapper namespace="com.example.dao.UserMapperProxy">
    <select id="getAllUsers" resultType="user">
        select * from user;
    </select>
</mapper>

两种开发方式demo

//传统方式
UserMapperManualImpl userMapper = new UserMapperManualImpl();
List list = userMapper.userList();
System.out.println(list);

//接口代理方式
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapperProxy mapperProxy = sqlSession.getMapper(UserMapperProxy.class);

List<User> allUsers = mapperProxy.getAllUser();
System.out.println(allUsers);

Mybatis基于配置文件的开发

导入相关依赖

<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
 </dependencies>

创建实体类数据库表

创建user表

image-20230206150752919

创建数据表对应java类

创建user类

package com.example.domain;

import java.util.Date;

public class User {

    private int id;
    private String name;
    private int money;
    private Date birthday;

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                ", birthday=" + birthday +
                '}';
    }
}

填写数据库的连接信息

示例

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456

创建Dao层mapper接口

package com.example.mapper;

import com.example.domain.User;
import java.util.List;

public interface UserMapper {
    public void addUser(User user);
    public User queryUserById(int id);
    public List<User> getAllUser();
}

创建mapper接口映射文件

配置文件标签

约束头

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

根标签

<mapper></mapper>

根标签属性

namespace:根标签的唯一限定名

子标签

子标签名称 功能
select 查询语句
delete 删除语句
update 修改语句
insert 插入语句
cache
cache-ref
parameterMap
resultMap
sql sql语句片段抽取

子标签属性

属性名 含义
id 子标签的唯一限定名
parameterType 指定传入的参数的类型
resultType 指定查询语句的结果类型
parameterMap
resultMap
databaseId
fetchSize
flushCache
lang
...

⭐动态SQL

根据用户输入或外部条件动态组合的SQL语句块。

all
元素 作用 备注
if 判断语句 单条件分支判断
choose(when、otherwise) 相当于java中的switch case语句 多条件分支判断
foreach 循环语句 常用在in语句等列举条件中
trim,where 辅助元素 用于除里一些SQL拼装问题
bind 辅助元素 拼接参数
if

对业务提交的数据进行判断,动态地生成需要执行的SQL语句

select * from user where id=#{id} and name=#{name} and money=#{money};

<select id="getUserByCondition" resultType="user" parameterType="user">
	select * from user
	<where>
		<if test="id!=0">
			id=#{id}
		</if>
		<if test="name!=null">
			and name=#{name}
		</if>
		<if test="money!=0">
			and money=#{money}
		</if>
	</where>
</select>
foreach

select * from user where id in (1,2,3);

<select id="getUserByCollection" resultType="user" parameterType="list" >
	select * from user
	<where>
		<foreach collection="list" open="id in(" close=")" item="id" separator=",">
			#{id}
		</foreach>
	</where>
</select>

代码示例

<?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="userMapper">

    <select id="queryById" resultType="user" parameterType="int">
        select * from user where id = #{id}
    </select>

    <select id="queryAll" resultType="user">
        select * from user;
    </select>

    <insert id="insertOne" parameterType="user">
        insert into user values(#{id},#{name},${money})
    </insert>

    <update id="updateById" parameterType="int">
        update user set money = #{money} where id=#{id}
    </update>

    <delete id="deleteByName" parameterType="string">
        delete from user where name = #{name}
    </delete>

</mapper>

创建xml核心配置文件

配置文件介绍

约束头

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

根标签

<configuration></configuration>

子标签

all

*号为常用标签

子标签名称 功能
properties 加载外部的properties文件
environments 数据源环境,
databaseIdProvider 数据库厂商标识,
mappers 加载映射配置,
objectFactory 对象工厂,
objectWrapperFactory 对象包装工厂,
plugins 插件,
reflectorFactory 反射器工厂,
settings 设置,
typeAliases 类型别名,
typeHandlers 类型处理器,
properties

properties存在子标签property

父标签 属性名 功能
properties resource 从项目的resources文件夹内加载资源
url 从远程URL加载资源
<properties resource="jdbc.properties"/>
<properties url="http://xxxx/jdbc.properties"/>
environments
父标签 子标签1 子标签2 子标签3 属性 可选值 属性功能
environments default development 指定默认的环境名称
environment id 指定当前环境的名称
transactionManager type JDBC 指定事务管理器
MANAGED
dataSource type POOLED 指定数据源类型
UNPOOLED
JNDI
property name
value 可使用el表达式设置值
<environments default="development">
	<environment id="development">
		<transactionManager type="JDBC"></transactionManager>
		<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>
	</environment>
</environments>
mappers
父标签 子标签1 属性名 属性功能
mappers mapper resource 使用相对于类路径的资源引用
url 使用完全限定资源定位符(URL)
class 使用映射器接口实现类的完全限定类名
package name 将包内所有的映射器接口全部注册为映射器
<mappers>
    <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
    <mapper url="file:///var/mappers/AuthorMapper.xml"/>
    <mapper class="org.mybatis.builder.AuthorMapper"/>
    <package name="org.mybatis.builder"/>
</mappers>
typeAliases
父标签 子标签1 属性名 属性功能
typeAliases typeAlias type 需要指定类(类全限定名)
alias 别名的名称
<typeAliases>
	<typeAlias type="org.example.domain.User" alias="user"/>
</typeAliases>
typeHandlers
父标签 子标签1 属性名 属性功能
typeHandlers typeHandler handler 指定handler类全限定名
<typeHandlers>
	<typeHandler handler="com.example.handler.DateTypeHandler"></typeHandler>
</typeHandlers>
plugins
父标签 子标签1 子标签2 属性名 属性功能
plugins plugin interceptor 指定使用的插件的类全限定名
property name
value
<plugins>
	<plugin interceptor="com.github.pagehelper.PageHelper">
		<property name="dialect" value="mysql"/>
	</plugin>
</plugins>

代码示例

<?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>

    <properties resource="jdbc.properties"/>

    <typeAliases>
        <typeAlias type="org.example.domain.User" alias="user"/>
    </typeAliases>


    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <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>
        </environment>
    </environments>

    <mappers>
        <mapper resource="org/example/mapper/userMapper.xml"></mapper>
    </mappers>
</configuration>

编写测试类

Mybatis的API使用

SqlSessionFactoryBuilder

SqlSession工厂构建器,通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

SqlSessionFactory

SqlSession工厂对象,创建SqlSession对象

//需要手动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession();
//设置自动提交事务
SqlSession sqlSession = sqlSessionFactory.openSession(true);

SqlSession

SqlSession会话对象,通过对象来执行sql语句、操作事务等

sqlSession.getMapper()//接口代理
sqlSession.select()//CRUD
sqlSession.commit()
sqlSession.close()

代码示例

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

List<User> list = sqlSession.selectList("userMapper.queryAll");
sqlSession.commit();

System.out.println(list);
sqlSession.close();

Mybatis基于注解的开发

创建实体类数据库表

创建数据表对应java类

⭐创建Dao层mapper映射接口

package com.example.mapper;

import com.example.domain.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface UserMapper {

    @Insert("insert into user values(#{id},#{name},#{money},#{birthday})")
    public void save(User user);

    @Update("update user set name=#{name},money=#{money} where id=#{id}")
    public void update(User user);

    @Delete("delete from user where id=#{id}")
    public void delete(int id);

    @Select("select * from user where id=#{id}")
    public User findById(int id);

    @Select("select * from user")
    public List<User> findAll();

}

创建properties属性文件

创建xml核心配置文件

与配置文件开发不同的唯一一点是注解开发mappers采用加载package包来加载

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
<!--    加载properties文件-->
    <properties resource="jdbc.properties"></properties>


<!--    数据源环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <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>
        </environment>
    </environments>

<!--    映射器-->
    <mappers>
        <package name="com.example.mapper"/>
    </mappers>

</configuration>

编写测试类