MyBatis框架的使用(笔记)

文章目录

  • MyBatis框架
    • 概要
    • MyBatis的使用
    • 其他配置
      • 动态SQL语句条件查询
      • 关联查询
      • 多形参
        • 传递列名
      • 存储过程调用

MyBatis框架

概要

MyBatis工作在数据访问层,此时的数据访问层就可以只编写 映射器接口 和 映射xml文件

使用场景:JavaSE、JavaEE(JavaWeb)

  • 映射器接口:供业务逻辑层使用,接口中根据需要定义方法,MyBatis框架负责创建实现这些接口的实例对象。接口命名以Mapper结尾,如:ProductMapper
  • 映射xml文件:其中包含了与映射器接口中的方法一一对应的SQL语句,且映射xml文件与映射器接口同名,例如:ProductMapper.xml
  • 核心xml配置文件:配置数据库连接参数以及MyBatis框架运行时参数

通过API类加载配置文件和映射器接口类,最后就可以在MyBatis中使用实例化的接口对象

  • 应用程序通过org.apache.ibatis.session.SqlSession接口与MyBatis框架进行交互
构造SqlSessionFactoryBuilder对象
构建出SqlSessionFactory对象
构建出SqlSession对象
获取映射器接口实例
对象 重量级 使用
SqlSessionFactory对象 重量级对象 创建一次
SqlSession对象 轻量级对象 可多次创建

MyBatis的使用

  1. 导入相关的jar包
    • 普通工程导入jar包时,直接复制粘贴到当前项目中。若使用IDEA,则还需手动添加到工程中。
    • Maven工程导入jar包时,在.pom配置文件中的dependencies元素下添加以下内容:
     
         <dependency>
             <groupId>org.mybatisgroupId>
             <artifactId>mybatisartifactId>
             <version>3.4.6version>
         dependency>
    
  2. 编写数据访问层的映射器接口和映射xml文件
  • 映射器接口
package com.MyBatis.demo.Dao;

import com.MyBatis.demo.bean.ProductInfo;

import java.util.List;
import java.util.Map;

public interface ProductMapper {
    /**
     * 根据商品Id查找商品信息
     * @param productId
     * @return
     */
    ProductInfo getInfoById(Integer productId);

    /**
     * 查找所有商品信息
     * @return
     */
    List<ProductInfo> findAllProducts(Map<String,String> map);

    /**
     * 保存商品信息
     * @param productInfo
     * @return
     */
    int saveInfo(ProductInfo productInfo);

    /**
     * 根据条件检索商品信息
     * @param condition(Name lowPrice highPrice typeid)
     * @return
     */
    List<ProductInfo> findByCondition(Map<String,Object> condition);

    /**
     * 更新商品类别编号
     * @param ids
     * @return
     */
    int updatePrdInfo(int[] ids);

    /**
     * 调用存储过程执行商品信息的查询
     * @param map
     */
    void findInfoByProcedure(Map<String,Object> map);

}
  • 映射xml文件
    • namespace属性值为 映射器接口 的完整类名
    • 根元素mapper的子元素selectupdateinsertdeleteid属性是映射xml文件对应的映射器接口的某个具体方法名
    • 根元素mapper的子元素updateinsertdelete不使用resultType属性,默认返回整数,代表该语句影响的记录条数
    • 元素insert的子元素selectKey表示查询主键,具有keyColumnkeyPropertyorderresultType属性,能将查询结果存进keyProperty指明的java对象属性中
      属性 说明
      keyColumn 主键对应的数据库列名
      keyProperty 主键对应的java对象属性名
      order 1.AFTER 父元素的SQL语句执行后执行
      2.BEFORE 父元素的SQL语句执行前执行
      resultType 主键返回的结果类型
      示例:
      <selectKey keyColumn="product_id" keyProperty="productId" resultType="int" order="BEFORE">
          select ifnull(max(product_id)+1,1)
          from products p
      selectKey>
      
      • 如果主键列是自增类型(auto_increment),元素insert可使用如下属性:
        <insert id="saveInfo" parameterType="ProductInfo" useGeneratedKeys="true" keyProperty="productId">
          ···
        insert>
        
    • 使用sql元素可定义可重用的sql片段,其中的id属性可唯一标识被引用的片段。引用语句如下:
      <include refid="id">include>
      
    • 元素的parameterTyperesultType属性分别表示参数类型、返回类型,resultMap属性表示结果类型映射(可重用)。
    • resultType属性和resultMap属性不能同时存在
    • 元素的parameterTyperesultType属性取值为自定义类的完整限定名或MyBatis预定义别名。
      • 若返回类型为列表类型或集合类型,则resultType属性设置为列表或集合中的元素类型
      • MyBatis预定义别名如下:
        别名 java类型 别名 java类型 别名 java类型
        _byte byte byte Byte decimal BigDecimal
        _long long long Long bigdecimal BigDecimal
        _short short short Short object Object
        _int int int Integer map Map
        _integer int integer Integer hashmap HashMap
        _double double double Double list List
        _float float float Float arraylist ArrayList
        _boolean boolean boolean Boolean collection Collection
        string String date Date iterator Iterator
    • 为解决<>在xml文件中的特殊语法,将包含<>的SQL语句包含在语句的空白处
    • SQL语句中的占位符使用#{ }#{ }${ }区别
      • 在映射xml文件根元素mapper的子元素selectupdateinsertdelete中的SQL语句对应于映射器接口中的方法
        • 若映射器接口方法的形参为基本类型,则占位符可表示该形参,例如:#{id}
        • 若映射器接口方法的形参为java对象,则占位符可表示该对象的属性,例如:#{productId}
          • 若占位符表示的值可能为null,则在占位符中添加指明jdbc数据类型,例如:#{price,jdbcType=DECIMAL}
          • jdbc数据类型与java数据类型对应关系如下:
            jdbcTyppe javaType
            TINYINT byte
            SMALLINT short
            INTEGER int
            INTEGER INTEGER
            INTEGER long
            BIGINT long
            FLOAT float
            ERAL float
            NUMERIC double
            DOUBLE double
            FLOAT double
            VARCHAR string
            CHAR string
            LONGVARCHAR string
            CLOB string
            BINARY byte[]
            VARBINARY byte[]
            LONGVARBINARY byte[]
            ARRAY array
            BIT boolean
            BOOLEAN boolean
            NUMERIC java.math.BigDecimal
            DECIMAL java.math.BigDecimal
            DATE java.sql.Date
            TIME java.sql.Time
            TIMESTAMP java.sql.Timestamp
            BLOB Blob
            CLOB Clob
            DISTINCT mapping of underlying type
            STRUCT struct
            REF Ref
            DATALINK java.net.URL[color=red][/color]
            • tinyint长度为1,即类型为:tinyint(1)查询时,该字段对应的Java类型为boolean
            • 将字段的java类型设置为Integer
              1. 在jdbcUrl添加参数:tinyInt1isBit=false(默认为true
              2. 避免使用长度为1的tinyint类型字段存储数字格式的数据
    • resultMap元素的type属性使用类的完整限定名,也可以使用在核心配置文件Configuration.xml中已定义过的简单别名
    • resultMap元素的子元素resultid(映射数据库主键)的column属性表示SQL语句在数据库中对应的列名,而property属性则表示的是java对象中的字段属性
    • 其他配置


<mapper namespace="com.MyBatis.demo.Dao.ProductMapper">

    <sql id="sql1">
        SELECT p.`product_id`,p.`name`,p.`product_type_id`,p.`price`,p.`description`
        FROM products p
    sql>
    
    <select id="getInfoById" parameterType="int" resultMap="mp1">
    

    select>

    <select id="findAllProducts" parameterType="map" resultMap="mp1">
        <include refid="sql1">include>
        ORDER BY ${colName}
    select>

    <select id="findByCondition" parameterType="map" resultMap="mp1">
        <include refid="sql1">include>
        <where>
            <if test="prdName!=null">p.`name` like CONCAT('%',#{prdName},'%')if>
            <if test="lowPrice!=null">=#{lowPrice}]]>if>
            <if test="highPrice!=null">if>
            <if test="typeId!=null">AND p.`product_type_id`=#{typeId}if>
        where>
    select>

    <update id="updatePrdInfo" parameterType="_int[]">
        UPDATE products p SET p.`product_type_id`=3 WHERE p.`product_id` IN
        <foreach collection="array" item="prdId" open="(" close=")" separator=",">
            #{prdId}
        foreach>
    update>

    <insert id="saveInfo" parameterType="productInfo">
        <selectKey keyColumn="product_id" keyProperty="productId" resultType="int" order="BEFORE">
            select ifnull(max(product_id)+1,1)
            from products p
        selectKey>
        INSERT INTO products
        VALUE(
        #{productId},
        #{proTypeId,jdbcType=INTEGER},
        #{productName},
        #{proDescription,jdbcType=VARCHAR},
        #{price,jdbcType=DECIMAL})
    insert>

    <select id="findInfoByProcedure" parameterType="map" statementType="CALLABLE">
        CALL pr_get_prd_info(#{prdId},
        #{prdName,mode=OUT,jdbcType=VARCHAR},
        #{typeId,mode=OUT,jdbcType=INTEGER},
        #{desc,mode=OUT,jdbcType=VARCHAR},
        #{price,mode=OUT,jdbcType=FLOAT})
    select>
    
    
    <resultMap type="productInfo" id="mp1">
        <id column="product_id" property="productId">id>
        <result column="product_type_id" property="proTypeId">result>
        <result column="name" property="productName">result>
        <result column="description" property="proDescription">result>
        <result column="price" property="price">result>
    resultMap>
    
mapper>

  1. 编写核心配置文件Configuration.xml
    • 主要配置数据库的连接参数和映射xml文件路径
      • 使用typeAliases元素设置类的简单名(仅首字母小写)取代类的全限定名,如下:

        <typeAliases>
            <typeAlias type="com.MyBatis.demo.bean.ProductInfo" alias="productInfo">typeAlias>
            <typeAlias type="com.MyBatis.demo.bean.ProductTypeInfo" alias="productTypeInfo">typeAlias>
        typeAliases>
        
      • transactionManager : 事务管理器

        类型 描述
        JDBC MyBatis默认使用的提交和回滚管理事务
        MANAGED 由容器管理事务 如:Spring
      • dataSource :配置数据源
        三种数据源 UNPOOLEDPOOLEDJNDI

         UNPOOLED  :  非池化 不采用连接池 的数据源
                      仅需配置driver url username password|
         POOLED    :  采用连接池的数据源
                      除配置driver url username password外
                      还可配置以下属性:
                      poolMaximumActiveConnections    最大活动连接数。默认值:10
                      poolMaximumIdleConnections      最大空闲连接数
                      poolMaximumCheckoutTime         池中连接的检查时间。默认值 20000毫秒(20秒)
         JNDI      :  从环境中获取数据源
        
 
<configuration>
    <typeAliases>
        <typeAlias type="com.MyBatis.demo.bean.ProductInfo" alias="productInfo">typeAlias>
        <typeAlias type="com.MyBatis.demo.bean.ProductTypeInfo" alias="productTypeInfo">typeAlias>
    typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC">transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/store?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
                <property name="poolMaximumIdleConnections" value="1"/>
                <property name="poolMaximumActiveConnections" value="5"/>
            dataSource>
        environment>
    environments>
    <mappers>
		<mapper resource="com/MyBatis/demo/Dao/ProductMapper.xml">mapper>
    mappers>
configuration>
  1. 编写代码加载MyBatis核心类,解析核心配置文件
    • 在Configuration.xml文件中,environments下可配置多套环境,但一个SqlSessionFactory实例只对应一种环境
    • 创建SqlSessionFactory实例时可指定环境
      • 默认环境
        SqlSessionFactoryBuilder().build(reader);
      • 指定环境id
        SqlSessionFactoryBuilder().build(Reader reader,String id);
String rs = "com/MyBatis/demo/Configuration.xml";
Reader reader = Resources.getResourceAsReader(rs);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
  1. 创建SqlSession实例并通过它获取映射器接口实例
    • SqlSession默认非自动提交事务,可手动提交,也可设置自动提交
SqlSession session = sqlSessionFactory.openSession();
//手动提交
session.commit();
//设置自动提交
SqlSession openSession(boolean autoCommit);
//获取映射器接口Mapper实例
UserMapper productMapper = session.getMapper(ProductMapper.class);
  1. 调用映射器接口中的方法执行数据处理
    ProductInfo productInfo = productMapper.getInfoById();
    
  2. 关闭SqlSession
    session.close();
    

其他配置

关于映射xml文件的配置

动态SQL语句条件查询

在映射xml文件中,根元素mapper的子元素selectupdateinsertdelete都可使用动态SQL语句进行条件查询

  • 元素
    • 包含子元素,以if元素的test属性内容作为判断条件动态的生成条件查询的SQL语句
    • if元素的test属性的判断条件有一个是成立的,则在where元素之前的SQL语句后面插入一个where
    • test属性的判断条件成立,则将if元素包含的SQL语句片段追加到已有的SQL语句片段上
    • 若追加到已有SQL语句片段上的内容以ANDOR开头,则将去掉ANDOR
      示例如下:
      <where>
          <if test="prdName!=null">p.`name` like CONCAT('%',#{prdName},'%')if>
          <if test="lowPrice!=null">=#{lowPrice}]]>if>
          <if test="highPrice!=null">if>
          <if test="typeId!=null">AND p.`product_type_id`=#{typeId}if>
      where>
      
    • 元素还含有子元素,子元素下含有whenotherwise子元素
      • 若遇到when元素的test属性判断条件成立,则仅将该when元素包含的SQL语句片段追加到已有的SQL语句片段之后
      • 若所有的when元素的test属性判断条件都不成立,则将otherwise元素中获得的SQL语句片段追加到已有的SQL语句片段之后
        • otherwise元素下包含子元素if
          示例如下:
      <where>
          <choose>
              <when test="productId!=null">product_id=#{productId}when>
              <otherwise>
                  <if test="productName!=null">and name like ···if>
                  <if test="typeId!=null">and ···if>
              otherwise>
          choose>
      where>
      
  • 元素
    • collection属性表示取值参数的数据类型,可以是集合或数组(array)、列表(list)
    • item属性表示用来指定迭代元素的变量名
    • open属性表示迭代元素在SQL语句中的起始符号
    • close属性表示迭代元素在SQL语句中的结束符号
    • separator属性表示迭代元素之间的分隔符
      示例如下:
    <update id="updatePrdInfo" parameterType="_int[]">
        UPDATE products p SET p.`product_type_id`=3 WHERE p.`product_id` IN
        <foreach collection="array" item="prdId" open="(" close=")" separator=",">
              #{prdId}
        foreach>
    update>
    

关联查询

查询时同时读取关联数据,只能使用元素和resultMap属性进行配置,不能使用resultType属性

resultMap元素中与关联查询相的子元素有:associationcollection

  • association元素
    • 关联数据类型为java对象
    • property属性表示关联数据对象在结果映射对象中的属性名
    • javaType属性表示关联数据对象在java中的数据类型名
    • 关联数据对象的属性封装使用idresult子元素
      示例如下:
      <resultMap id="map2" type="productInfo">
          <id column="product_id" property="productId">id>
          <result column="name" property="productName">result>
          <result column="description" property="proDescription">result>
          <result column="price" property="price">result>
          <association property="typeInfo" javaType="productTypeInfo">
              <id column="product_type_id" property="typeId">id>
              <result column="type_name" property="typeName">result>
          association>
      resultMap>
      
  • collection元素
    • 关联数据类型为集合
    • property属性表示关联集合在结果映射对象中的属性名
    • javaType属性表示关联集合在java中的数据类型名(简单名或全限定名)
    • ofType属性表示关联集合中的元素在java中的数据类型(简单名或全限定名)
    • 关联集合的元素存放使用idresult子元素
      示例如下:
      <resultMap id="mapl" type="productTypeInfo">
          <id column="product_type_id" property="typeId">id>
          <result column="type_name" property="typeName">result>
          <collection property="products" javaType="java.util.Set" ofType="productInfo">
              <id column="product_id" property="productId">id>
              <result column="name" property="productName">result>
              <result column="description" property="proDescription">result>
              <result column="price" property="price">result>
          collection>
      resultMap>
      
    • 也可以直接使用resultMap属性对关联集合的元素进行存放
      例如:
      <collection property="products" resultMap="rm3"/>
      

多形参

映射器接口方法传递多个形参时在xml配置中无需使用parameterType属性

  • 在xml配置文件中使用占位符#{ }进行形参传递
    故此以映射器接口中方法签名中形参出现的顺序在xml配置文件中分别使用#{arg0}#{arg1}#{arg2}#{arg3}···表示
    • 如果参数可能为null,则需指明jdbc数据类型
      例如:
    <insert id="saveInfo2">
          INSERT INTO products
          VALUE(
          0,
          #{arg1,jdbcType=INTEGER},
          #{arg0},
          #{arg2,jdbcType=VARCHAR},
          #{arg3,jdbcType=DECIMAL})
      insert>
    

传递列名

  1. #{ }传递的是映射器接口方法中的形参
    经过MyBatis转换为占位符?
  2. ${ }传递的是以形参表示的数据库中的列名
    经过MyBatis直接替换为数据库中的列名
    也可在${ }内传入一段SQL语句片段,例如:${ORDER BY p.price}
    • 传递列名的形参类型为自定义类或Map对象
      例如:
      <select id="findAllProducts" parameterType="map" resultMap="mp1">
         SELECT p.`product_id`,p.`name`,p.`product_type_id`,p.`price`,p.`description`
         FROM products p
         ORDER BY ${colName}
      select>
      

存储过程调用

根元素mapper下子元素insertselectdeleteupdate均可调用存储过程

通过子元素insertselectdeleteupdatestatementType属性指明SQL语句的类型
statementType属性值有:CALLABLEPREPAREDSTATEMENT
statementType属性默认属性值为:PREPARED

  • CALLABLE对应jdbcCallableStatement语句对象类型,表示SQL语句为存储过程调用
  • PREPARED对应jdbcPreparedStatement语句对象类型,表示SQL语句为预编译语句
  • STATEMENT对应jdbcStatement语句对象类型,表示SQL语句
  • MySQL中存储过程的创建和使用
    • 创建存储过程之前,使用DELIMITER //指明存储过程的结束符为//
    • 存储过程创建完成使用DELIMITER ;恢复为SQL语句的结束符为;
      • DELIMITER用以声明当前语句的结束符
    • BEGIN表示存储过程的开始,END表示存储过程的结束
    • OUT表示传出数据
      IN表示传入数据
      INOUT表示既传出也传入数据
    • 关键字CALL表示调用存储过程
      示例如下:
      DELIMITER //
      create procedure pr_get_prd_info(p_prd_id Int,OUT p_prd_name varchar(30),OUT p_type_id int,OUT p_desc varchar(50),OUT p_price Float)
      BEGIN
        select product_type_id,name,description,price
        into p_type_id,p_prd_name,p_desc,p_price
        from products p
        where product_id=p_prd_id;
      END
      //
      DELIMITER ;
      
      CALL pr_get_prd_info(···)
      
      
  • 在映射器接口中与调用存储过程相对应的方法返回类型为void
    实参类型应为封装的自定义类或Map集合
    • 仅能实参传形参
  • 在传递参数时,使用mode属性指明传递模式,jdbcType指明jdbc类型
    • mode属性传递模式的属性值有:
      1. OUT表示传出数据
      2. IN表示传入数据
      3. INOUT表示既传出也传入数据
        存储过程xml配置如下:
<select id="findInfoByProcedure" parameterType="map" statementType="CALLABLE">
    CALL pr_get_prd_info(#{prdId},
    #{prdName,mode=OUT,jdbcType=VARCHAR},
    #{typeId,mode=OUT,jdbcType=INTEGER},
    #{desc,mode=OUT,jdbcType=VARCHAR},
    #{price,mode=OUT,jdbcType=FLOAT})
select>

注意:

存储过程调用之前需确认是否授权
可在MySQL中授权
也可在SQLyog中的用户管理->对象级别特权中选择EXECUTECREATE ROUTINEALTER ROUTINE

你可能感兴趣的:(后端数据库框架,mybatis,java,后端)