淘先锋技术网

首页 1 2 3 4 5 6 7

Mybatis

持久层的概念

就是将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏,在断电或者其他情况下,重新开启系统仍然可以读取这些数据。

Mybatis的特点

1.不屏蔽SQL,能够更加精确地定位SQL语句,可以对其进行优化和改造。

2.提供强大、灵活的映射机制。

3.在Mybatis中,提供了使用Mapper的接口编程,只要一个接口和一个XML就能创建映射器,进一步简化我们的工作。

下面会通过介绍来展示Mybatis的特点

搭建环境

导入maven依赖或者去官网下载jar包

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>

了解Mybatis的核心组件

SQLSessionFactoryBuilder(构造器)

它会根据配置或者代码来生成SqlSessionFactory,采用的是分布构建的Builder模式。

SqlSessionFactory(工厂接口)

依靠它来生成SqlSession,使用的是工厂模式。

SqlSession(会话)

一个既可以发送SQL执行返回结果,也可以获取Mapper的接口。在现有的技术中,一般我们会让其在业务逻辑代码中“消失”,而使用的是Mybatis提供的SQL Mapper接口编程技术,它可以提高代码的可读性和可维护性。

SQL Mapper(映射器)

Mybatis新设计存在的组件,它由一个Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。

逐一介绍这些组件:

SqlSessionFactory(工厂接口)

使用Mybatis首先是使用配置或者代码去生产SqlSessionFactory,而Mybatis提供了构造器SqlSessionFactoryBuilder.采用的是Builder模式。在Mybatis中,既可以通过读取配置的XML文件的形式去生成SqlSessionFactory,也可以通过Java代码的形式去生成SqlSessionFactory。建议使用XML

使用XML构建SqlSessionFactory

首先,在Mybatis中的XML分为两类,一类是基础配置文件,通常只有一个,主要是配置一些最基本的上下文参数和运行环境;另外一类是映射文件,他可以配置映射关系、SQL、参数等信息。

基础配置文件,命名为mybatis-config.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>
    <!--别名-->
    <typeAliases>
        <typeAlias type="com.spring.domain.Role" alias="role"/>
    </typeAliases>
    <!--数据库环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="username" value="root"/>
                <property name="password" value="pzh200061"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?useSSL=false"/>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件-->
    <mappers>
        <mapper resource="com/spring/mapper/RoleMapper.xml"></mapper>
    </mappers>
</configuration>

描述基础配置文件:

元素定义了一个别名role,它代表着com.spring.domain.Role这个类。这样定义后,在Mybatis上下文中就可以使用别名去代替全限定名了。

元素的定义,这里描述的是数据库。它里面的 元素是配置食物管理器,这里采用的是MyBatis的JDBC管理器方式。然后采用去配置数据源,其中属性type="POOLED"代表采用MyBatis内部提供的连接池方式,最后定义一些关于JDBC的属性信息。

元素代表引入的那些映射器。

通过上面的基础配置文件,就可以用代码生成SqlSessionFactory了

public class MybatisConfig {
    SqlSessionFactory sqlSessionFactory = null;
    String resource = "mybatis-config.xml";
    InputStream inputStream;
    
    public void config(){
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        
    }

    public static void main(String[] args) {
        MybatisConfig config = new MybatisConfig();
    }
}

首先读取mybatis-config.xml,然后通过SqlSessionFactoryBuilder的Builder方法去创建SqlSessionFactory.

SqlSession

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzzt5HFp-1608705504433)(C:\Users\pzh\AppData\Roaming\Typora\typora-user-images\image-20201203135820665.png)]

在Mybatis中,SqlSession是其核心接口。在MyBatis中有两个实现类,DefaultSqlSession和SqlSessionManager.DefaultSqlSession是单线程使用的,而SqlSessionManager是多线程环境下使用的。SqlSession的作用类似于一个JDBC中的Connection对象,代表着一个连接资源的启用。它的作用有三个:

获取Mapper接口

发送SQL给数据库

控制数据库事务

SqlSession的创建

public class MybatisConfig {
    SqlSessionFactory sqlSessionFactory = null;
    String resource = "mybatis-config.xml";
    InputStream inputStream;
    SqlSession sqlSession = null;

    public void config(){
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    
    public void createSqlSession(){
        //打开SqlSession会话
        sqlSession = sqlSessionFactory.openSession();
        try {
             sqlSession.commit();//提交事务       
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();//回滚事务
        }finally {
            //关闭资源
            if(sqlSession != null){
                sqlSession.close();
            }
        }
        
    }

    public static void main(String[] args) {
        MybatisConfig config = new MybatisConfig();
        config.config();
        config.createSqlSession();
    }
}

映射器

映射器时MyBatis中最重要、最复杂的组件,它由一个接口和对应的XML文件(或注解)组成。它可以配置一下内容:

描述映射规则

提供SQL语句,并可以配置SQL参数类型、返回类型、缓存刷新等信息。

配置缓存。

提供动态SQL。

基于XML文件的形式

首先新建一个POJO

public class Role {
    private Long id;
    
    private String roleName;
    
    private String note;

    public Role(){

    }

    public Role(Long id, String roleName, String note) {
        this.id = id;
        this.roleName = roleName;
        this.note = note;
    }

    public Long getId() {
        return id;
    }

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

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", roleName='" + roleName + '\'' +
                ", note='" + note + '\'' +
                '}';
    }
}

映射器的主要作用就是将SQL查询到的结果映射为一个POJO,或者将POJO的数据插入到数据库中,并定义一些关于缓存等的重要内容。

新建一个roles表

在这里插入图片描述

首先定义一个接口:

public interface RoleMapper {
    public Role getRole(Long id);
}

之前定义的mybatis-config.xml文件中配置了这样一段代码:

<!--映射文件-->
<mappers>
    <mapper resource="com/spring/mapper/role/RoleMapper.xml"/>
</mappers>

它的作用就是引入一个XML文件。用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 namespace="com.spring.mapper.role.RoleMapper">
    <select id="getRole" parameterType="long" resultType="role">
        select id,roleName,note from roles where id = #{id}
    </select>
</mapper>

这样就完成了一个映射器的定义。

元素中的属性namespace所对应的是一个接口的全限定名,于是Mybatis上下文就可以通过它找到对应的接口。

元素表明这是一条查询语句,而属性id标识了这条SQL,属性parameterType="long"说明传递给SQL的是一个long型的参数,而resultYtpe="role"表示返回的是一个role类型的返回值。而role是之前配置文件mybatis-config.xml配置的别名。

这条SQL中的#{id}表示传递进去的参数。

注解实现映射器
public interface RoleMapper2 {
    @Select("select id,roleName,note from roles where id = #{id}")
    public Role getRole(Long id);
}

SQLSession发送SQL

有了映射器之后就能够通过SqlSession发送SQL了。我们以getRole这条SQL为例看看如何发送SQL。

package com.spring.config;

import com.spring.domain.Role;
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.InputStream;

public class MybatisConfig {
    SqlSessionFactory sqlSessionFactory = null;
    String resource = "mybatis-config.xml";
    InputStream inputStream;
    SqlSession sqlSession = null;

    public void config(){
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void createSqlSession(){
        //打开SqlSession会话
        sqlSession = sqlSessionFactory.openSession();
        try {
             sqlSession.commit();//提交事务
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();//回滚事务
        }

    }

    public void roleTest(){
        Role role = sqlSession.selectOne("com.spring.mapper.RoleMapper.getRole",1L);
        System.out.println(role);
        if(sqlSession!=null){
            sqlSession.close();
        }
    }

    public static void main(String[] args) {
        MybatisConfig config = new MybatisConfig();
        config.config();
        config.createSqlSession();
        config.roleTest();
    }
}
执行结果:Role{id=1, roleName='小明', note='弟弟'}

用Mapper接口发送SQL

public void mapperTest(){
    RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
    System.out.println(roleMapper.getRole(1L));
    if(sqlSession!=null){
        sqlSession.close();
    }
}

通过SqlSession的getMapper方法来获取一个Mapper接口,就可以调用它的方法了。因为XML文件或者接口注解定义的SQL都可以通过“类的全限定名+方法名"查找,所以MyBatis会启用对应的SQL进行运行,并返回结果。

增删改查实现

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 namespace="com.spring.mapper.RoleMapper">
    <select id="getRole" parameterType="long" resultType="role">
        select id,roleName,note from roles where id = #{id}
    </select>
    <insert id="insertRole" parameterType="role">
        insert into roles(roleName,note) values (#{roleName},#{note})
    </insert>
    <delete id="deleteRole" parameterType="long">
        delete from roles where id = #{id}
    </delete>
    <update id="updateRole" parameterType="role">
        update roles set roleName = #{roleName},note = #{note}
        where id = #{id}
    </update>
    <select id="findRoles" parameterType="string" resultType="role">
        select id,roleName,note
        from roles
        where roleName like concat('%',#{roleName},'%')
    </select>
</mapper>

接口定义:

package com.spring.mapper;

import com.spring.domain.Role;

import java.util.List;

public interface RoleMapper {
    public Role getRole(Long id);
    public int deleteRole(Long id);
    public int updateRole(Role role);
    public int insertRole(Role role);
    public List<Role> findRoles(String roleName);
}

插入

package com.spring.config;

import com.spring.domain.Role;
import com.spring.mapper.RoleMapper;
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.InputStream;

public class MybatisConfig {
    private static volatile SqlSessionFactory sqlSessionFactory = null;
    final static String resource = "mybatis-config.xml";
    static InputStream inputStream;
    SqlSession sqlSession = null;

    public static SqlSessionFactory getSqlSessionFactory(){
        if(sqlSessionFactory==null){
            synchronized (MybatisConfig.class){
                if(sqlSessionFactory==null){
                    try {
                        inputStream = Resources.getResourceAsStream(resource);
                        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        return sqlSessionFactory;
    }

    public void insertRole(Role role){
        //打开SqlSession会话
        sqlSession = sqlSessionFactory.openSession();
        try {
             RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
            System.out.println(roleMapper.insertRole(role));
             sqlSession.commit();//提交事务
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();//回滚事务
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }

    }

    public static void main(String[] args) {
        MybatisConfig.getSqlSessionFactory();
        MybatisConfig config = new MybatisConfig();
        Role role = new Role("小李","叔叔");
        config.insertRole(role);
    }
}

删除:

public void deleteRole(long id){
    //打开SqlSession会话
    sqlSession = sqlSessionFactory.openSession();
    try {
        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
        System.out.println(roleMapper.deleteRole(id));
        sqlSession.commit();//提交事务
    }catch (Exception e){
        e.printStackTrace();
        sqlSession.rollback();//回滚事务
    }finally {
        if(sqlSession!=null){
            sqlSession.close();
        }
    }
}

修改

public void updateRole(Role role){
    //打开SqlSession会话
    sqlSession = sqlSessionFactory.openSession();
    try {
        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
        System.out.println(roleMapper.updateRole(role));
        sqlSession.commit();//提交事务
    }catch (Exception e){
        e.printStackTrace();
        sqlSession.rollback();//回滚事务
    }finally {
        if(sqlSession!=null){
            sqlSession.close();
        }
    }
}

查询

public void findRoles(String roleName){
    //打开SqlSession会话
    sqlSession = sqlSessionFactory.openSession();
    try {
        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
        List<Role> roles = roleMapper.findRoles(roleName);
        for(Role role : roles){
            System.out.println(role);
        }
        sqlSession.commit();//提交事务
    }catch (Exception e){
        e.printStackTrace();
        sqlSession.rollback();//回滚事务
    }finally {
        if(sqlSession!=null){
            sqlSession.close();
        }
    }
}

Mybatis配置

<?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="datasource.properties"/>

    <!--别名-->
    <typeAliases>
        <typeAlias type="com.spring.domain.Role" alias="role"/>
    </typeAliases>

    <!--数据库环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="username" value="root"/>
                <property name="password" value="pzh200061"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=CTT"/>
            </dataSource>
        </environment>
    </environments>
    <!--映射文件-->
    <mappers>
        <mapper resource="mapper/RoleMapper.xml"/>
    </mappers>
</configuration>

Mybatis映射

         <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="username" value="root"/>
            <property name="password" value="pzh200061"/>
            <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=CTT"/>
        </dataSource>
    </environment>
</environments>
<!--映射文件-->
<mappers>
    <mapper resource="mapper/RoleMapper.xml"/>
</mappers>