MyBatis

1 什么是MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作,使得程序员在开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程,花更多的精力在业务开发中。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJOPlain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2 MyBatis全局配置文件基础设置

2.1 配置顺序

在这里插入图片描述

2.2 属性(properties)

属性可以在外部进行配置,可以进行动态替换。如:

	<!-- resource属性:用于指定properties配置文件的位置,要求配置文件必须在类路径下 -->
	<properties resource="jdbcConfig.properties">
		<!-- 启用默认值特性 -->
		<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
	</properties>

默认值特性参考官网例子:

	<dataSource type="POOLED">
	  <!-- ... -->
	  <property name="username" value="${username:ut_user}"/> <!-- 如果属性 'username' 没有被配置,'username' 属性的值将为 'ut_user' -->
	</dataSource>

2.3 设置(settings)

 	<settings>
        <!--
            开启二级缓存的支持
            cacheEnabled:全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。
        -->
        <setting name="cacheEnabled" value="true"/>

        <!--
            延迟加载
            lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。
            aggressiveLazyLoading:开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载。
        -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

        <!--
            multipleResultSetsEnabled:是否允许单个语句返回多结果集(需要数据库驱动支持)。
        -->
        <setting name="multipleResultSetsEnabled" value="true"/>
    </settings>

2.4 类型别名(typeAliases)

    <typeAliases>
        <!-- 单个别名定义 -->
        <!-- <typeAlias alias="user" type="com.hc.domain.User"/> -->

        <!-- 批量别名定义,扫描包下的类,别名为类名(首字母大写或小写都行) -->
        <package name="com.hc.domain"/>
    </typeAliases>

2.5 插件(plugins)

分页插件如下:

	<plugins>
        <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>

2.6 环境配置(environments)

	<!-- 和Spring整合后environments配置将被废除 -->
    <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:root}"/>  <!-- 默认值 -->
                <property name="password" value="${jdbc.password:1234}"/>
            </dataSource>
        </environment>
    </environments>

2.7 映射器(mappers)

    <mappers>
        <!--XML配置文件-->
        <!-- <mapper resource="com/hc/dao/UserDao.xml"/> -->

        <!--注解配置-->
        <!--<mapper class="com.hc.dao.UserDao"></mapper>-->

        <!-- 注册指定包下的所有mapper接口,此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中 -->
        <package name="com.hc.dao"/>
    </mappers>

3 基于MyBatis实现单表CRUD(XML)

3.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>HelloMybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>9</maven.compiler.source>
        <maven.compiler.target>9</maven.compiler.target>
    </properties>

    <dependencies>
        <!--MyBatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--数据库依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <!--日志依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3.2 SqlMapConfig.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>
    <!-- 1.properties属性引入外部配置文件 -->
    <!-- resource属性:用于指定properties配置文件的位置,要求配置文件必须在类路径下 -->
    <properties resource="jdbcConfig.properties">
        <!-- 启用默认值特性 -->
        <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
    </properties>

    <!-- 2.配置延迟加载和缓存 -->
    <settings>
        <!--
            开启二级缓存的支持
            cacheEnabled:全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。
        -->
        <setting name="cacheEnabled" value="true"/>

        <!--
            延迟加载
            lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。
            aggressiveLazyLoading:开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载。
        -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>

        <!--
            multipleResultSetsEnabled:是否允许单个语句返回多结果集(需要数据库驱动支持)。
        -->
        <setting name="multipleResultSetsEnabled" value="true"/>


    </settings>

    <!-- 3.类型别名配置 -->
    <typeAliases>
        <!-- 单个别名定义 -->
        <!-- <typeAlias alias="user" type="com.hc.domain.User"/> -->

        <!-- 批量别名定义,扫描包下的类,别名为类名(首字母大写或小写都行) -->
        <package name="com.hc.domain"/>
    </typeAliases>

    <!-- 4.environments数据库环境配置 -->
    <!-- 和Spring整合后environments配置将被废除 -->
    <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:root}"/>  <!-- 默认值 -->
                <property name="password" value="${jdbc.password:1234}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 5.加载映射文件 -->
    <mappers>
        <!--XML配置文件-->
        <!-- <mapper resource="com/hc/dao/UserDao.xml"/> -->

        <!--注解配置-->
        <!--<mapper class="com.hc.dao.UserDao"></mapper>-->

        <!-- 注册指定包下的所有mapper接口,此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中 -->
        <package name="com.hc.dao"/>
    </mappers>
</configuration>

3.3 User类、UserDao接口

package com.hc.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    // 多对多:一个用户可以拥有多个账户
    private List<Account> accounts;

    // 多对多:一个用户可以赋予多个角色
    private List<Role> roles;

    /**
     * Mybatis框架会调用这个默认构造方法来构造实例对象,即实体类需要通过Mybatis进行动态反射生成。
     * 反射的Class.forName("className").newInstance();需要对应的类提供一个无参构造函数。
     */
    public User() {
    }

    public User(Integer id, String username, Date birthday, String sex, String address) {
        this.id = id;
        this.username = username;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                ", accounts=" + accounts +
                ", roles=" + roles +
                '}';
    }
}

package com.hc.dao;

import com.hc.domain.QueryVo;
import com.hc.domain.User;

import java.util.List;

public interface UserDao {
    
    User findOneById(Integer id);

    List<User> findAllByName(String username);

    List<User> findAllByCondition(User user);

    List<User> findAllByQueryVo(QueryVo queryVo);

    List<User> findAllAndAccount();

    List<User> findAllAndRole();

    List<User> findAll();

    int findTotal();

    void insertOne(User user);

    void updateOne(User user);

    void deleteOne(Integer id);
}

3.4 UserDao.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.hc.dao.UserDao">

    <!-- 缓存配置 -->
    <cache/>

    <!-- 可被其它语句引用的可重用语句块 -->
    <sql id="defaultSql">
        select *
        from user
    </sql>

    <!-- 描述如何从数据库结果集中加载对象 -->
    <resultMap id="userMap" type="User">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="address" property="address"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>

        <!--
            collection是用于建立一对多中集合属性的对应关系,ofType用于指定集合元素的数据类型
            此处采用延迟加载,等需要账户信息时再查询。
         -->
        <collection column="id" property="accounts" ofType="Account" select="com.hc.dao.AccountDao.findOneById">
        </collection>
    </resultMap>

    <!--多表查询,一个用户的所有角色信息-->
    <resultMap id="userRoleMap" type="User">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <result column="address" property="address"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>

        <!-- collection是用于建立一对多中集合属性的对应关系,ofType用于指定集合元素的数据类型-->
        <collection property="roles" ofType="Role">
            <id column="rid" property="roleId"></id>
            <result column="role_name" property="roleName"></result>
            <result column="role_desc" property="roleDesc"></result>
        </collection>
    </resultMap>

    <!--
        根据id查询用户,useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来。
    -->
    <select id="findOneById" parameterType="java.lang.Integer" resultType="com.hc.domain.User" useCache="true">
        select *
        from user
        where id = #{id};
    </select>

    <!-- 根据用户名模糊查询 -->
    <select id="findAllByName" parameterType="java.lang.String" resultType="com.hc.domain.User">
        <!-- select * from user where username like #{name}; -->   <!-- 使用#{},原理是使用占位符,PrepareStatement语句 -->
        select * from user where username like '%${value}%';         <!-- 使用${},原理是使用字符串拼接,当然${value}的写法固定 -->
    </select>

    <!-- 根据条件查询,采用if标签判断User类中的存在不存在 -->
    <!-- where标签替代where 1 = 1语句的功能 -->
    <select id="findAllByCondition" resultType="User" parameterType="User">
        <include refid="defaultSql"></include>
        <where>
            <if test="username != null and username != ''">
                and username like #{username}
            </if>
            <if test="address != null">
                and address like #{address}
            </if>
        </where>
    </select>

    <!-- 根据QueryVo包装类进行查询 -->
    <select id="findAllByQueryVo" parameterType="QueryVo" resultType="User">
        <include refid="defaultSql"></include>
        <where>
            <if test="ids != null and ids.size() > 0">
                <foreach collection="ids" open="id in (" close=")" item="id" separator=",">
                    <!--
                        item="id",此id与#{id}名称需保持一致
                    -->
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

    <select id="findAllAndAccount" resultMap="userMap">
        select * from user;
    </select>

    <!-- 查询所有用户及其角色信息 -->
    <select id="findAllAndRole" resultMap="userRoleMap">
        select u.*, r.*
        from user u
                 left outer join user_role ur on ur.uid = u.id
                 left outer join role r on r.id = ur.rid
    </select>


    <!-- 查询所有 -->
    <select id="findAll" resultType="user">
        select *
        from user;
    </select>

    <!-- 查询总用户数 -->
    <select id="findTotal" resultType="int">
        select count(1)
        from user;
    </select>

    <!-- 插入新用户 -->
    <insert id="insertOne" parameterType="com.hc.domain.User">
        <!--
            配置保存时获取插入的id,id是数据库自动增长的。
            keyProperty:Java表中字段;keyColumn:数据库中表中字段;resultType:返回类型;order:执行顺序。
         -->
        <selectKey keyProperty="id" keyColumn="id" resultType="Integer" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user(username, birthday, sex, address)
        values (#{username}, #{birthday}, #{sex}, #{address});
    </insert>

    <!-- 更新用户 -->
    <update id="updateOne" parameterType="com.hc.domain.User">
        update user
        set username = #{username},
            birthday = #{birthday},
            sex=#{sex},
            address=#{address}
        where id = #{id};
    </update>

    <!--
         删除用户,如果仅有一个参数,#{id}中的id名字可以任意指定
    -->
    <delete id="deleteOne" parameterType="java.lang.Integer">
        delete
        from user
        where id = #{id};
    </delete>
</mapper>

3.5 测试

import com.hc.dao.UserDao;
import com.hc.domain.QueryVo;
import com.hc.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class testMybatis {

    private InputStream in;
    private SqlSessionFactoryBuilder builder;
    private SqlSessionFactory factory;
    private SqlSession session;
    private UserDao userDao;

    @Before
    public void init() throws Exception {
        // 1.从 XML 中构建 SqlSessionFactory
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        // 2.使用SqlSessionFactory生产SqlSession对象
        session = factory.openSession(true);
        // 3.使用SqlSession创建dao接口的代理对象
        userDao = session.getMapper(UserDao.class);
    }

    @After
    public void destroy() throws Exception {
        // 关闭资源
        session.close();
        in.close();
    }

    /**
     * 根据id查询用户
     *
     * @throws Exception
     */
    @Test
    public void testFindOneById() throws Exception {
        User user = userDao.findOneById(49);

        // 关闭SqlSession和清除SqlSession的缓存都会重新进行数据库的查询
        // session.close();
        // session.commit();
        session.clearCache();

        User user01 = userDao.findOneById(49);

        // true说明该用户是同一个用户
        System.out.println(user == user01);
    }

    /**
     * 根据姓氏模糊查询用户
     *
     * @throws Exception
     */
    @Test
    public void testFindAllByName() throws Exception {
        List<User> users = userDao.findAllByName("覃");
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 根据条件执行查询所有方法
     *
     * @throws Exception
     */
    @Test
    public void testFindAllByCondition() throws Exception {
        User user = new User(null, "HC", new Date(), "男", "湖南岳阳");
        List<User> users = userDao.findAllByCondition(user);
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 根据条件执行查询所有方法
     *
     * @throws Exception
     */
    @Test
    public void testFindAllByQueryVo() throws Exception {
        QueryVo queryVo = new QueryVo();
        List<Integer> list = new ArrayList<>();
        list.add(41);
        list.add(42);
        queryVo.setIds(list);
        List<User> users = userDao.findAllByQueryVo(queryVo);
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 查询所有用户及其账户信息
     *
     * @throws Exception
     */
    @Test
    public void testFindAllAndAccount() throws Exception {
        List<User> users = userDao.findAllAndAccount();
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 查询所有用户及其角色信息
     *
     * @throws Exception
     */
    @Test
    public void testFindAllAndRole() throws Exception {
        List<User> users = userDao.findAllAndRole();
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 执行查询所有方法
     *
     * @throws Exception
     */
    @Test
    public void testFindAll() throws Exception {
        List<User> users = userDao.findAll();
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * 查询总的记录数
     *
     * @throws Exception
     */
    @Test
    public void testFindTotal() throws Exception {
        System.out.println(userDao.findTotal());
    }

    /**
     * 插入一个User对象
     */
    @Test
    public void testInsertOne() {
        User user = new User(null, "HC", new Date(), "男", "湖南岳阳");
        System.out.println("添加用户前:" + user.toString());
        userDao.insertOne(user);
        session.commit();  // 提交事务
        System.out.println("添加用户后:" + user.toString());
    }

    /**
     * 更新一个User对象
     */
    @Test
    public void testUpdateOne() {
        User user = new User(49, "覃杰", new Date(), "男", "湖北恩施");

        userDao.updateOne(user);
        session.commit();
    }

    /**
     * 删除一个User对象
     */
    @Test
    public void testDeleteOne() {
        userDao.deleteOne(48);
        session.commit();
    }

    @Test
    public void testTwoCache() {

        SqlSession session1 = factory.openSession();
        UserDao userDao1 = session1.getMapper(UserDao.class);
        User user01 = userDao1.findOneById(49);
        session1.clearCache();

        SqlSession session2 = factory.openSession();
        UserDao userDao2 = session1.getMapper(UserDao.class);
        User user02 = userDao2.findOneById(49);
        session2.clearCache();

        // 尽管使用了二级缓存,但是这二者也不是同一个对象,因为从SqlSessionFactory拿出的数据创建一个新的对象返回
        System.out.println(user01 == user02);
    }


}

4 Mapper.xml探索

MyBatis的用法参见官方文档

4.1 占位符${}#{}

参照此

4.2 resultMap

  • resultType:指定结果集的类型,支持基本类型和实体类类型。注意,当实体类的属性名和查询的列名不一致时,封装会失败。
    <select id="findAll" resultType="user">
        select *
        from user;
    </select>
  • resultMap:建立查询的列名和实体类的属性名称不一致时建立对应关系,多对对查询时都会使用到resultMap。假设如下关系:一个套餐中包含多个检查组,而一个检查组中包含多个检查项。现在的要求是需要通过套餐的id值查询出所有的检查组信息和检查项信息。
    <resultMap id="baseResultMap" type="com.hc.pojo.Setmeal">
        <id column="id" property="id"></id>
        <result column="name" property="name"/>
        <result column="code" property="code"/>
        <result column="helpCode" property="helpCode"/>
        <result column="sex" property="sex"/>
        <result column="age" property="age"/>
        <result column="price" property="price"/>
        <result column="remark" property="remark"/>
        <result column="attention" property="attention"/>
        <result column="img" property="img"/>
    </resultMap>

    <resultMap id="findByIdResultMap" type="com.hc.pojo.Setmeal" extends="baseResultMap">
        <!--
            collection是用于建立一对多中集合属性的对应关系
                property用于指定“com.hc.pojo.Setmeal”中的属性
                ofType用于指定集合元素的数据类型
                column用于指定需要传入select="com.hc.dao.CheckGroupDao.findCheckGroupById"查询的参数
        -->
        <collection property="checkGroups" javaType="ArrayList" ofType="com.hc.pojo.CheckGroup" column="id"
                    select="com.hc.dao.CheckGroupDao.findCheckGroupById"/>
    </resultMap>
    <!--根据id查询套餐-->
    <select id="findById" parameterType="int" resultMap="findByIdResultMap">
        select *
        from t_setmeal
        where id = #{id}
    </select>
    <resultMap id="baseResultMap" type="com.hc.pojo.CheckGroup">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="code" property="code"/>
        <result column="helpCode" property="helpCode"/>
        <result column="sex" property="sex"/>
        <result column="remark" property="remark"/>
        <result column="attention" property="attention"/>
    </resultMap>

    <resultMap id="findByIdResultMap" type="com.hc.pojo.CheckGroup">
        <collection property="checkItems" javaType="ArrayList" ofType="com.hc.pojo.CheckItem" column="id"
                    select="com.hc.dao.CheckItemDao.findCheckItemById"/>
    </resultMap>
    <!--根据套餐-检查组中间表查询-->
    <select id="findCheckGroupById" resultMap="findByIdResultMap">
        select *
        from t_checkgroup
        where id in (select checkgroup_id
                     from t_setmeal_checkgroup
                     where setmeal_id = #{id}
        )
    </select>
    <select id="findCheckItemById" resultType="com.hc.pojo.CheckItem">
        select *
        from t_checkitem
        where id in (select checkitem_id from t_checkgroup_checkitem where checkgroup_id = #{id})
    </select>

4.3 MyBatis连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。它可以减少我们获取连接所消耗的时间,连接池里面有若干连接,每个线程需要连接的时候就取一个出来,用完了就把连接放回去,连接池本质上就是一个存储连接的容器,也可以理解为一个集合对象且该集合必须是线程安全的,不能两个线程拿到同一个连接。同时,该集合还要实现队列的特性——先进先出。

4.3.1 分类

Mybatis连接池一般分为以下三类:

  • UNPOOLED:不使用连接池的数据源,MyBatis 会创建 UnpooledDataSource 实例。
    在这里插入图片描述
  • POOLED:使用连接池的数据源,MyBatis 会创建 PooledDataSource 实例。
    在这里插入图片描述
  • JNDI: 使用JNDI实现数据源。

4.3.2 配置

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

4.3.3 分析

MyBatis配置使用连接池的数据源后,会创建PooledDataSource 实例。
在这里插入图片描述
可以看到,PooledDataSource 实例中持有一个UnpooledDataSource,也就是说当PooledDataSource需要创建java.sql.Connection对象时,还是通过UnpooledDataSource来创建,PooledDataSource 只是提供一种缓存连接池机制。注意,只有当SqlSession对象要去执行SQL语句时,MyBatis才会去调用DataSource对象创建java.sql.Connection,毕竟数据库连接是比较珍贵的资源。

4.4 主键自增与返回、缓存、动态SQL和延迟加载

参照此

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是聪聪黄吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值