MyBatis

MyBatis

MyBatis环境配置

maven配置

pom.xml:

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

mybatis-congig.xml

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。

在这里插入图片描述

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>
    <!--驼峰命名转换-->
    <settings>
        <!--goods_id ==> goodsId-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--设置默认指向的数据库-->
  <environments default="development">
      <!--配置环境,不同的环境不同的id名字-->
    <environment id="development">
        <!--采用JDBC方式对数据库事务进行commit/roolback-->
      <transactionManager type="JDBC"/>
        <!--采用连接池方式管理数据库连接-->
      <dataSource type="POOLED">
          <!--配置数据库连接驱动-->
        <property name="driver" value="${driver}"/>
          <!--配置数据库地址-->
        <property name="url" value="${url}"/>
          <!--数据库用户名-->
        <property name="username" value="${username}"/>
          <!--数据库密码-->
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
    <mappers>
        <mapper resource="{映射sql语句的xml文件路径}"/>
    </mappers>
</configuration>

SqlSessionFactory

SqlSessionFactory

SqlSessionFactory是MyBatis的核心对象

用于初始化MyBatis,创建SqlSession对象

保证SqlSessionFactory在应用中全局唯一

SqlSession

SqlSession是MyBatis操作数据库的核心对象

SqlSession使用JDBC方式与数据库交互

SqlSession对象提供了数据表CRUD对应方法

MyBatisUtils包装类

package com.imooc.mybatis.utils;

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.Reader;

/**
 * MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
 */
public class MyBatisUtils {
    //利用static属性类不属于对象,且全局唯一
    private static SqlSessionFactory sqlSessionFactory=null;
    //利用静态块在初始类时实例化sqlSessionFactory
    static{
        try {
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            e.printStackTrace();
            //初始化错误时,通过抛出异常通知调用者
            throw new ExceptionInInitializerError(e);
        }
    }

    /**
     * openSession创建一个新的SqlSession对象
     * @return SqlSession对象
     */
    public static SqlSession openSession(){
        return sqlSessionFactory.openSession();
    }

    /**
     * 释放一个有效的SqlSession对象
     * @param session 准备释放SqlSession对象
     */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}

SQL语句的映射

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

在一个 XML 映射文件中,可以定义无数个映射语句,这样一来,XML 头部和文档类型声明部分就显得微不足道了。文档的其它部分很直白,容易理解。 它在命名空间 “org.mybatis.example.BlogMapper” 中定义了一个名为 “selectBlog” 的映射语句,这样你就可以用全限定名 “org.mybatis.example.BlogMapper.selectBlog” 来调用映射语句了,就像上面例子中那样:

Blog blog =(Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

名字空间

命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

**命名解析:**为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。

  • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
  • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。

作用域和生命周期

SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

try{
	//逻辑代码
}catch(){
}finally{
	关闭SqlSession连接
}

映射器

mybatis-config.xml

mappers标签里面保存映射的xml文件

<!-- 使用相对于类路径的资源引用 -->
<mappers>
        <mapper resource="文件.xml"/>
</mappers>

这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了

映射文件

在mapper标签里面写要处理的sql语句

分别由select、insert、update、delete标签

<?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="goods">
    <select id="selectAll" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods order by goods_id desc limit 10
    </select>
    <!--单参数传参,使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数-->
    <select id="selectById" parameterType="Integer" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods where goods_id=#{value}
    </select>
    <!--多参数传参时,使用parameterType指定Map接口,SQL中#{key}提取参数-->
    <select id="selectByPriceRange" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods where current_price between #{min} and #{max} order by current_price limit 0,#{limit}
    </select>
<!--    利用LinkedHashMap保存多表关联结果
        MyBatis会将每一条记录包装为LinkedHashMap对象
        key是字段名 value是字段对应的值,字段类型根据表结构进行自动判断
        优点:易于扩展,易于使用
        缺点:太过灵活,无法进行编译时检查
-->
    <select id="selectGoodsMap" resultType="java.util.LinkedHashMap">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
<!--    结果映射-->
    <resultMap id="rmGoods" type="com.imooc.mybatis.dto.GoodsDTO">
<!--        设置主键字段与属性映射-->
        <id property="goods.goodsId" column="goods_id"></id>
<!--        设置非主键字段与属性映射-->
        <result property="goods.title" column="title"></result>
        <result property="goods.originalCost" column="original_cost"></result>
        <result property="goods.currentPrice" column="current_price"></result>
        <result property="goods.discount" column="discount"></result>
        <result property="goods.isFreeDelivery" column="is_free_delivery"></result>
        <result property="goods.categoryId" column="category_id"></result>
        <result property="categoryName" column="category_name"></result>
        <result property="test" column="test"></result>
    </resultMap>
    <select id="selectGoodsDTO" resultMap="rmGoods">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
    <insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>
    <update id="update" parameterType="com.imooc.mybatis.entity.Goods">
        update t_goods set title=#{title},
                           sub_title=#{subTitle},
                           original_cost=#{originalCost},
                           current_price=#{currentPrice},
                           discount=#{discount},
                           is_free_delivery=#{isFreeDelivery},
                           category_id=#{goodsId}
        where goods_id=#{goodsId}
    </update>
    <delete id="delete" parameterType="Integer">
        delete from t_goods where goods_id=#{value}
    </delete>
</mapper>

XML映射器

SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

  • cache – 该命名空间的缓存配置。
  • cache-ref – 引用其它命名空间的缓存配置。
  • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
  • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
  • sql – 可被其它语句引用的可重用语句块。
  • insert – 映射插入语句。
  • update – 映射更新语句。
  • delete – 映射删除语句。
  • select – 映射查询语句。

select

查询语句是 MyBatis 中最常用的元素之一——光能把数据存到数据库中价值并不大,还要能重新取出来才有用,多数应用也都是查询比修改要频繁。 MyBatis 的基本原则之一是:在每个插入、更新或删除操作之间,通常会执行多个查询操作。因此,MyBatis 在查询和结果映射做了相当多的改进。

无参数形式的select映射语句:
<mapper namespace="goods">
	 <!--无参数形式的select语句映射-->
    <select id="selectAll" resultType="com.imooc.mybatis.entity.Goods">
        select * from t_goods order by goods_id desc limit 10
    </select>
</mapper>
单参数形式的select语句:
<mapper namespace="goods">
	 <select id="selectById" parameterType="Integer" resultType="com.imooc.mybatis.entity.Goods">
    	select * from t_goods where goods_id=#{value}
    </select>
</mapper>

单参数传参,使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数,其中#{value}是固定的写法

多参数形式的select映射语句
<mapper namespace="goods">
	 <select id="selectById" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
    	select * from t_goods where current_price between #{min} and #{max} 
         order by current_price limit 0,#{limit}
    </select>
</mapper>

多参数传参时,使用parameterType指定Map接口,SQL中#{key}提取参数 ,此案例中Map容器中存有max和min两个键值对,sql中提取参数分别使用#{max}和#{min}来分别提取响应的参数

多表关联查询结果
<mapper namespace="goods">
	 <select id="selectGoodsMap" resultType="java.util.LinkedHashMap">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
</mapper>

​ 利用LinkedHashMap保存多表关联结果
​ MyBatis会将每一条记录包装为LinkedHashMap对象
​ key是字段名 value是字段对应的值,字段类型根据表结构进行自动判断
​ 优点:易于扩展,易于使用
​ 缺点:太过灵活,无法进行编译时检查

select标签的参数以及含义

id:名字空间中唯一的标识符,可以被用来引用这条语句。

resultType:期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。

parameterType:将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

resultMap:对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。

结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

<mapper namespcae="goods">
<!--    结果映射-->
    <resultMap id="rmGoods" type="com.imooc.mybatis.dto.GoodsDTO">
<!--        设置主键字段与属性映射-->
        <id property="goods.goodsId" column="goods_id"></id>
<!--        设置非主键字段与属性映射-->
        <result property="goods.title" column="title"></result>
        <result property="goods.originalCost" column="original_cost"></result>
        <result property="goods.currentPrice" column="current_price"></result>
        <result property="goods.discount" column="discount"></result>
        <result property="goods.isFreeDelivery" column="is_free_delivery"></result>
        <result property="goods.categoryId" column="category_id"></result>
        <result property="categoryName" column="category_name"></result>
        <result property="test" column="test"></result>
    </resultMap>
    <select id="selectGoodsDTO" resultMap="rmGoods">
        select g.*,c.category_name,'1' as test from t_goods g,t_category c where g.category_id=c.category_id
    </select>
</mapper>
resultMap的属性:

id:当前命名空间中的一个唯一标识,用于标识一个结果映射。

type:类的完全限定名, 或者一个类型别名(关于内置的类型别名,可以参考上面的表格)。

id&result

这些元素是结果映射的基础。idresult 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。

这两者之间的唯一不同是,id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

id和result的属性:

property:映射到列结果的字段或属性。如果 JavaBean 有这个名字的属性(property),会先使用该属性。否则 MyBatis 将会寻找给定名称的字段(field)。 无论是哪一种情形,你都可以使用常见的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。

column:数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。

insert、update、delete

数据变更语句 insert,update 和 delete 的实现非常接近

<mapper namespcae="goods">
	 <insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>
    <update id="update" parameterType="com.imooc.mybatis.entity.Goods">
        update t_goods set title=#{title},
                           sub_title=#{subTitle},
                           original_cost=#{originalCost},
                           current_price=#{currentPrice},
                           discount=#{discount},
                           is_free_delivery=#{isFreeDelivery},
                           category_id=#{goodsId}
        where goods_id=#{goodsId}
    </update>
    <delete id="delete" parameterType="Integer">
        delete from t_goods where goods_id=#{value}
    </delete>
</mapper>
insert、update、delete元素的属性:

id:名字空间中唯一的标识符,可以被用来引用这条语句。

parameterType:将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

useGeneratedKeys:(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。

keyProperty:(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。

keyColumn:(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

自动生成主键的字段

如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了,例如, Author 表已经在 id 列上使用了自动生成,那么语句可以修改为:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

如果你的数据库还支持多行插入, 你也可以传入一个 Author 数组或集合,并返回自动生成的主键。

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>

或下面这种方法,

<insert id="insert" parameterType="com.imooc.mybatis.entity.Goods">
        insert into t_goods (title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id)
        values(#{title},#{subTitle},#{originalCost},#{currentPrice},#{discount},#{isFreeDelivery},#{categoryId})
        <!--帮助主键回添-->
        <selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>

在进行sql语句执行完成之后,执行selectkey,把主键添加到Goods类的goodsId属性中

此方法还可以用于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动。

动态SQL

在这里插入图片描述

动态SQL把SQL语句的where子句变成where标签通过if标签判断选取符合规则的子句

本案例中通过if标签中的test属性判断Map容器中的categoryId或currentPrice键是否为空,来选择对应的where子句

mybatis中缓存

一级缓存

一级缓存是 SqlSession级别 的缓存。在操作数据库时需要构造 sqlSession 对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的 sqlSession 之间的缓存数据区域(HashMap)是互相不影响的。用一张图来表示一下一级缓存,其中每一个 SqlSession 的内部都会有一个一级缓存对象。

img

在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的SQL,MyBatis 提供了一级缓存的方案优化这部分场景,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询,提高性能。

一级缓存时执行commit,close,增删改等操作,就会清空当前的一级缓存;当对SqlSession执行更新操作(update、delete、insert)后并执行commit时,不仅清空其自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)。

MyBatis 一级缓存最大的共享范围就是一个SqlSession内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存

二级缓存

当二级缓存开启后,同一个命名空间(namespace) 所有的操作语句,都影响着一个共同的 cache,也就是二级缓存被多个 SqlSession 共享,是一个全局的变量。当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

二级缓存开启条件

二级缓存默认是不开启的,需要手动开启二级缓存,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。

在mapper标签中写下cache子标签进行配置

<mapper namespace="xxx">
	<cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
</mapper>
cache标签的属性

eviction是缓存的清楚策略,当缓存对象数量达到上限后,自动触发对应算法对缓存对象清楚
1.LRU-最近最久未使用:移除最长时间不被使用的对象
o1 o2 o3 o4…o512
14 99 83 1 893
2.FIFO-先进先出:按对象进入缓存的顺序来移除它们
3.SOFT-软引用:移除基于垃圾收集器状态和软引用规则的对象
4.WEAK:弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象
flushInterval 代表间隔多长时间自动清空缓存,单位毫秒,600000ms=10min
size 缓存存储上线,用于保存对象或集合(1个集合算一个对象)的数量上限
readOnly 设置为true,代表返回只读缓存,每次从缓存取出的是缓存对象本身。这种执行效率较高
设置为false,代表每次取出的是缓存对象的“副本”,每一次取出的对象都是不同的,这种安全性较高

取消SQL语句的二级缓存
select标签

useCache=“false”代表不开启缓存

insert、update、delete标签

flushCache="true"在执行SQL语句后立即强制清空缓存

或 java语句 session.commit()提交事务数据后强制清空缓存

OneToMany对象关联查询

在 MyBatis 中,通过 元素的子元素 处理一对多级联关系,collection 可以将关联查询的多条记录映射到一个 list 集合属性中。

<collection property="orderList"
        ofType="net.biancheng.po.Order" column="id"
        select="net.biancheng.mapper.OrderMapper.selectOrderById" />

在 元素中通常使用以下属性。

  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)。
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。

一对多关联查询可采用以下两种方式:

  • 分步查询,通过两次或多次查询,为一对多关系的实体 Bean 赋值
  • 单步查询,通过关联查询实现

MyBatis整合C3P0连接池

由于MyBatis框架使用的是数据库本身自带的连接池,功能没有第三方厂商研发的连接池功能强大,所以我们要使用其他厂商的连接池。这里我们使用C3P0连接池来演示。

maven

引入C3P0的依赖

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>

创建C3P0与MyBatis兼容使用的数据源工厂类

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;

/**
 * C3P0与MyBatis兼容使用的数据源工厂类
 */
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
    public C3P0DataSourceFactory() {
        this.dataSource=new ComboPooledDataSource();
    }
}

更改默认连接池为C3P0连接池

<!--            采用连接池方式管理数据库连接-->
<!--            <dataSource type="POOLED">-->
            <dataSource type="com.imooc.mybatis.datasource.C3P0DataSourceFactory">
                <property name="driverClass" value="com.mysql.jdbc.Driver"/>
                <property name="jdbcUrl"
                          value="jdbc:mysql://localhost:3306/babytun?useUnciode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="yaoshuaixiang"/>
                <!--初始数据库连接池的连接数量-->
                <property name="initialPoolSize" value="5"/>
                <!--连接池的最大连接数量-->
                <property name="maxPoolSize" value="20"/>
                <!--连接池的最小连接数量-->
                <property name="minPoolSize" value="5"/>
            </dataSource>

MyBatis批出理

采用foreach标签进行循环插入

Mybatis foreach 标签用于循环语句,它很好的支持了数据和 List、set 接口的集合,并对此提供遍历的功能。语法格式如下

<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
    参数值
</foreach>

foreach 标签主要有以下属性,说明如下。

  • item:表示集合中每一个元素进行迭代时的别名。
  • index:指定一个名字,表示在迭代过程中每次迭代到的位置。
  • open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
  • separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
  • close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。

使用 foreach 标签时,最关键、最容易出错的是 collection 属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下 3 种情况:

  • 如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
  • 如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
  • 如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。

进行批处理操作

<!--INSERT INTO table-->
    <!--VALUES ("a" , "a1" , "a2"),("b" , "b1" , "b2"),(....)-->
    <insert id="batchInsert" parameterType="java.util.List">
        INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.title},#{item.subTitle}, #{item.originalCost}, #{item.currentPrice}, #{item.discount}, #{item.isFreeDelivery}, #{item.categoryId})
        </foreach>
    </insert>

MyBatis注解

注解说明
@Insert实现新增
@Delete实现删除
@Update实现更新
@Select实现查询
@Result实现结果集封装
@Results可以与@Result 一起使用,封装多个结果集
@ResultMap实现引用@Results 定义的封装
@One实现一对一结果集封装
@Many实现一对多结果集封装
@SelectProvider实现动态 SQL 映射
@CacheNamespace实现注解二级缓存的使用

使用注解实现复杂关系映射开发

实现复杂关系映射 ,之前我们可以在映射文件中通过配置<resultMap>来实现,在使用注解开发时我们需要借助@Results 注解,@Result 注解,@One 注解,@Many 注解。

复杂关系映射的注解说明

@Results 注解

代替的是标签<resultMap>
该注解中可以使用单个@Result 注解,也可以使用@Result 集合
@Results({@Result(),@Result()})或@Results(@Result())

@Resutl 注解

代替了<id> 标签和<result>标签

@Result 中的属性介绍:
@Result中的属性介绍
id是否是主键字段
column数据库的列名
property需要装配的属性名
one需要使用的@One 注解(@Result(one=@One)()))
many需要使用的@Many 注解(@Result(many=@many)()))
@One 注解(一对一)

代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。
使用格式:@Result(column=" “,property=”",one=@One(select=""))

@Many 注解(多对一)

代替了标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般为 ArrayList)但是注解中可以不定义。
使用格式:@Result(property="",column="",many=@Many(select=""))

段 |
| column | 数据库的列名 |
| property | 需要装配的属性名 |
| one | 需要使用的@One 注解(@Result(one=@One)())) |
| many | 需要使用的@Many 注解(@Result(many=@many)())) |

@One 注解(一对一)

代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。
使用格式:@Result(column=" “,property=”",one=@One(select=""))

@Many 注解(多对一)

代替了标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般为 ArrayList)但是注解中可以不定义。
使用格式:@Result(property="",column="",many=@Many(select=""))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Alonzo de blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值