Mybatis | Mybatis的核心配置

目录:

  • [Mybatis的核心配置 :](#Mybatis的核心配置 :)
    • [一、MyBatis的 "核心对象"](#一、MyBatis的 “核心对象”)
      • [1.1 SqlSessionFactory](#1.1 SqlSessionFactory)
      • [1.2 SqlSession :](#1.2 SqlSession :)
        • [SqlSession对象中的操作数据库的方法 :](#SqlSession对象中的操作数据库的方法 :)
          • [\<T> T selectOne ( String statement )](#<T> T selectOne ( String statement ))
          • [\<T> T selectOne( String statement , Object parameter )](#<T> T selectOne( String statement , Object parameter ))
          • [\<E> List\<E> selectList ( String statement )](#<E> List<E> selectList ( String statement ))
          • [\<E> List\<E> selectList ( String statement , Object parameter )](#<E> List<E> selectList ( String statement , Object parameter ))
          • [\<E> List\<E> selectList ( String statement , Object parameter , RowBounds rowBounds )](#<E> List<E> selectList ( String statement , Object parameter , RowBounds rowBounds ))
          • [void select ( String statement , Object parameter , ResultHandler handler )](#void select ( String statement , Object parameter , ResultHandler handler ))
          • [int insert ( String statement )](#int insert ( String statement ))
          • [int insert ( String statement , Object parameter )](#int insert ( String statement , Object parameter ))
          • [int update( String statement )](#int update( String statement ))
          • [int update( String statement , Object parameter)](#int update( String statement , Object parameter))
          • [int delete( String statement )](#int delete( String statement ))
          • [int delete( String statement , Object parameter)](#int delete( String statement , Object parameter))
          • [int commit( )](#int commit( ))
          • [void rollback( )](#void rollback( ))
          • [void close( )](#void close( ))
          • [\<T> T getMapper( Class\<T> type )](#<T> T getMapper( Class<T> type ))
          • [Connection getConnection( )](#Connection getConnection( ))
        • [使用工具类创建 "SqlSession" / SqlSession工具类](#使用工具类创建 “SqlSession” / SqlSession工具类)
    • [二、MyBatis的 "配置文件"](#二、MyBatis的 “配置文件”)
    • [三、MyBatis的 "映射文件"](#三、MyBatis的 “映射文件”)
      • ["配置文件"中的 "主要元素"](#“配置文件”中的 “主要元素”)

Mybatis的核心配置 :

一、MyBatis的 "核心对象"

  • 在使用MyBatis 框架时,主要涉及 两个核心对象 : SqlSessionFactorySqlSession,它们在MyBatis框架 中起着至关重要作用

1.1 SqlSessionFactory

  • SqlSessionFactory 是MyBatis 框架中十分重要对象,它是单个数据库映射关系 经过编泽后内存镜像,其主要作用创建SqlSession

  • SqlSessionFactory 对象的实例可以通过 SqlSessionFactoryBuilder对象 来构建,而SqlSessionFactoryBuilder 对象 则可以通过 XML配置文件 或一个预先定义好Configuration实例 构建出SqlSessionFactory实例

  • 以下内容 讲解的是 :就是 通过XML配置文件 构建出的SqlSessionFactory实例,其实现代码如下:

    java 复制代码
    InputStream inputStream = Resources.getResourceAsStream("配置文件的位置");
    //通过SqlSessionFactoryBuilder的 build()方法 + 配置文件来创建 SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = 
        new SqlSessionFactoryBuilder().build(inputStream);
  • SqlSessionFactory对象线程安全 的,它一旦被创建,在整个应用执行期间都会存在 。如果我们多次地创建同一个数据库的SqlSessionFactory,那么此数据库的资源将很容易被耗尽。为了解决此问题,通常每一个数据库 都会只对应一个 SqlSessionFactory , 所以在 构建SqlSessionFactory实例 时,建议使用单列模式

1.2 SqlSession :

  • SqlSession 是MyBatis 框架中另一个重要对象 , 它是 应用程序持久层 之间执行与操作的一个单线程对象,其主要作用执行持久化操作

  • SqlSession对象 包含数据库 中所有执行SOL操作方法SqlSession 中有很多操作数据库方法 ),由于其底层封装JDBC连接 ,所以可以直接使用SqlSession实例 来 执行已映射SQL语句

    (可用SqlSession 来执行 "映射文件 " 中的sql语句)。

  • 每一个线程都 应该有一个自己的SqlSession实例 ,并且该实例不能被共享 的。同时,SqlSession实例线程不安全 的,因此 其使用范围 最好在 一次请求一个方法 中,绝不能 将其放在一个静态字段实例字段任何类型的管理范围 (如Servlet的HttpSession)中使用。

  • 使用完SqlSession对象 之后,要及时地关闭它 ,通常可以将其放在fnally块中关闭

java 复制代码
//通过 sqlSessionFactory对象获得"SqlSession"
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
   //此处执行持久化操作
}finally{
   sqlSession.close();
}
SqlSession对象中的操作数据库的方法 :
<T> T selectOne ( String statement )

<T> T selectOne ( String statement ) : 查询方法 : 参数 statement 是在 " 映射文件" 中定义的 <select>元素id
目的是 : 获得映射文件 中的 "<select>元素下所代表的 sql语句 作为 selectOne( )方法的参数 ")。使用该方法后,会返回执行SQL语句查询结果一条泛型对象

<T> T selectOne( String statement , Object parameter )

<T> T selectOne ( String statementObject parameter ) :查询方法 : 参数 statement 是在 " 映射文件" 中定义的 <select>元素idparameter查询所需参数。使用该方法后,会返回执行SQL语句查询结果一条泛型对象

<E> List<E> selectList ( String statement )

<E> List<E> selectList ( String statement ) : 查询方法 : 参数 statement 是在 "映射文件 " 中定义的 <select>元素id 。使用该方法后,会返回执行SQL语句查询结果泛型对象集合

<E> List<E> selectList ( String statement , Object parameter )

<E> List<E> selectList ( String statement , Object parameter ) : 查询方法 : 参数 statement 是在 " 映射文件 " 中定义的 <select>元素id , parameter 是查询所需的参数 。使用该方法后,会返回 执行SQL语句查询结果的 泛型对象集合

<E> List<E> selectList ( String statement , Object parameter , RowBounds rowBounds )

<E> List<E> selectList ( String statement , Object parameter ) : 查询方法 : 参数==statement ==是在 " 映射文件 " 中定义的 <select>元素id , parameter 是查询所需的参数 ,rowBounds是用于分页参数对象 。使用该方法后会返回 执行SQL语句查询结果的 泛型对象集合

void select ( String statement , Object parameter , ResultHandler handler )

void select ( String statement, Object parameter,ResultHandler handler ) : 查询方法 : 参数statement 是在配置文件中定义的 <select>元素idparameter 是查询所需的 参数ResultHandler对象 用于处理查询返回复杂结果集。 (通常用于多表查询

int insert ( String statement )

int insert ( String statement ) : 插入方法 : 参数 statement 是在 "映射文件 " 中定义的 <select>元素id ,使用该方法后,会返回执行 SQL语句所影响行数

int insert ( String statement , Object parameter )

int insert ( String statement , Object parameter ) : 插入方法 : 参数 statement 是在 " 映射文件 " 中定义的 <select>元素idparameter 是查询所需的参数 。使用该方法后,会返回执行 SQL语句所影响行数

int update( String statement )

int update ( String statement ) : 更新方法 : 参数 statement 是在 " 映射文件 " 中定义的 <update>元素id ,使用该方法后,会返回执行 SQL语句所影响行数

int update( String statement , Object parameter)

int update ( String statement , Object parameter ) : 更新方法 : 参数 statement 是在 " 映射文件 " 中定义的 <update>元素idparameter更新 所需的参数 。使用该方法后,会返回执行 SQL语句所影响行数

int delete( String statement )

int delete ( String statement ) : 删除方法 : 参数 statement 是在 "映射文件 " 中定义的 <delete>元素id ,使用该方法后,会返回执行 SQL语句所影响行数

int delete( String statement , Object parameter)

int delete ( String statement , Object parameter ) : 删除方法 : 参数 statement 是在 " 映射文件 " 中定义的 <delete>元素idparameter删除 所需的参数 使用该方法后,会返回执行 SQL语句所影响行数

int commit( )

int commit ( ) : 提交事务方法

void rollback( )

int rollback ( ) : 回滚事务方法

void close( )

int close ( ) : 关闭SqlSession 对象。

<T> T getMapper( Class<T> type )
  • <T> T getMapper ( Class<T> type ) : 该方法 会返回 Mapper接口代理对象,该对象关联了SqlSession对象 ,开发人员可以使用对象直接调用方法操作数据库 。参数type是Mapper的接口类型。MyBatis官方推荐通过
    Mapper 对象访问MyBatis
  • 该方法 : getMapper( ) 的目的是根据传入的 类类型type 返回一个与该类型匹配的对象。具体实现可能涉及反射机制,用于 创建并返回 一个与传入类类型相匹配实例
Connection getConnection( )

Connection getConnection( ) : 获取 JDBC数据库连接对象 的方法。

使用工具类创建 "SqlSession" / SqlSession工具类
  • 使用工具类 创建 "SqlSession "对象 :

    java 复制代码
    package com.myh.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.InputStream;
    
    
    /**
     * 工具类
     */
    public class SqlSessionUtils {  //获得SqlSession的"工具类"
    
        private static SqlSessionFactory sqlSessionFactory = null;
        //初始化 SqlSessionFactory 对象
        static { //静态代码块
            try {
                //使用Mybatis提供的Resources类加载mybatis-config.xml配置文件
                InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
                //构建SqlSessionFactory工厂
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获得SqlSession对象的静态方法
         */
        public static SqlSession getSession() {
            return sqlSessionFactory.openSession();
        }
    }

    这样,我们在使用时就 只创建了一个SqlSessionFactory 对象,并且可以通过工具类getSession( ) 方法, 来 获取SqlSession对象

二、MyBatis的 "配置文件"

MyBatis的核心配置文件 中,包含了很多 影响MyBatis 行为的重要信息 。这些信息通常在一个项目中只会在一个配置文件中编写,并且编写后也不会轻易改动。

"映射文件"中的 "主要元素"

  • MyBatis 框架的 核心配置文件 (即 mybatis-config.xml )中,<configuration> 元素 是配置文件的 根元素其他元素 都要在 <configuration> 元素内配置。

  • Mybatis配置文件主要元素图 :(要熟悉 <configuration>元素 各个子元素配置。)

    ps :

    ==<Cofgnaion>子元素 必须按照图中由上到下 ==的顺序进行配置,否则Mybatis 在解新xml配置文件的时候会报错。

<properties>元素
  • <properties> 是一个配置属性元素 ,该元素通常用于将内部配置 "外在化",即通过外部的配置 来动态地替换内部定义的属性

(直接的使用 : 将外部的 Xxx.properties文件 中的属性 用于 mybatis配置文件 中 )。

例如,数据库的连接等属性,就可以通过典型的 Java属性文件 ( .properties文件 )中的配置替换

ps :

当我们在mybatis 配置文件中 使用 <properties>元素 导入 .properties文件 时,即可在mybatis配置文件 中,即直接使用 .properties文件 中的数据

db.properties

properties 复制代码
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = root

mybatis-config.xml

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>
   <!-- properties属性 -->
   <!-- 通过properties属性引入 .properties配置文件, mybatis配置文件中则可直接使用 .properties中的数据,进行"动态替换"  -->
   <properties resource="db.properties"/>

   <!-- environments属性 -->
   <environments default="mysql">
       <environment id="mysql">
           <transactionManager type="JDBC"/>
           <dataSource type="POOLED">
               <!--
               通过"properties属性"来将 以下的driver、url、username、password 和
               .properties配置文件 中的数据进行"动态替换"
               -->
               <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>

</configuration>

完成上述配置后,dataSource 中连接数据库的4个属性 ( driverurlusermamepassword 值将会由db.properties文件对应的值动态替换。这样就为配置提供了诸多灵活的选择。

除了可以像上述通过外部配置文件定义属性值 外,还可以通过配置 <properties>元素 的子元素 <property> ,以及通过方法参数传递 的方式来获取属性值 。由于使用properties配置文件 来配置属性值 可以方便地多个配置文件使用这些属性值 ,并且方便日后的维护和修改,所以在实际开发中,使用.properties 文件来配置属性值最常用的方式

<settings>元素
  • <settings>元素 主要用于改变MyBatis运行时行为,例如 开启二级缓存开启延迟加载 等。

    虽然不配置<settings>元素,也可以正常运行MyBatis, 但是熟悉<settings>的配置内容以及它们的作用还是十分必要的。

  • 常见的**<settings>属性配置在 "配置文件" 中的使用** :

    xml 复制代码
        <settings>
            <setting name="cacheEnabled" value="true" />
            <setting name="lazyLoadingEnabled" value="true" />
            <setting name="multipleResultSetsEnabled" value="true"/>
            <setting name="useColumnLabel" value="true"/>
            <setting name="useGeneratedKeys" value="false" />
            <setting name="autoMappingBehavior" value="PARTIAL"/>
             .....
        </settings>
<typeAliases>元素
  • <typeAliases>元素 用于为配置文件 中的Java类型 设置一个简短的名字 ,即 设置别名别名 的设置与XML配置 相关,其使用的意义 在于减少全限定类名冗余。 如 : 可用 <typeAliases>元素POJO类 设置一个 "别名"。

    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元素 为 typeAliases元素的 "子元素"  -->
            <typeAlias alias="user" type="com.myh.po.Customer"/>
        </typeAliases>
    
    </configuration>

    上述示例中,<typeAliases> 元素子元素 <typeAlias> 中的type属性 用于指定需要被定义别名 的类的全限定名alias属性 的属性值user 就是自定义的别名 ,它可以代替com.myh.po.Customer使用在MyBatis文件任何位置 。如果省略alias属性 ,MyBatis 会默认将类名首字母 小写后 的名称作为别名

  • POJO类过多时,还可以通过自动扫描包形式自定义别名 (此时以类名首字母小写后 的名称为 "别名"),具体示例如下 :

    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>
            <!--   使用自动扫描包来定义"别名"  -->
            <!--   Mybatis会将所用 com.myh.po包中POJO类以首字母小写的名称 作为"别名" -->
            <!--   如: Customer 的 默认设置的别名为: customer  -->
            <package name="com.myh.po"/>
        </typeAliases>
    
    </configuration>
  • 需要注意 的是,上述方式的别名只适用于没有使用注解 的情况。如果 在程序中使用了注解 ,则别名其注解的值, 具体如下 :

    java 复制代码
    //使用注解来为该POJO类设置在 mybatis-config.xml配置文件中使用的 "别名"
    @Alias(value = "customer")
    public class Customer {  
          .....
    }
  • 除了可以使用 <typeAliases>元素自定义别名 外,MyBatis框架还默认 为许多常见的Java类型 (如数值字符串日期集合 等 )提供了 相应的类型别名 。(可使用时查询常见的Java类型别名是什么

<typeHandler>元素
  • MyBatis预处理语句( PreparedStatement )中 设置一个参数 或者从结果集 ( ResultSet )中取出一个值 时,都会用其框架内部 注册了的 typeHandler ( 类型处理器 ) 进行相关处理

  • typeHandler作用 就是将预处理语句 中传入的参数从 javaType ( Java类型) 转换为 jdbcType
    ( JDBC类型) ,或者从数据库取出结果 时将 jdbcType 转换为 javaType

  • 为了方便转换 ,Mybatis框架提供了一系列默认的类型处理器

    类型处理器 Java 类型 JDBC 类型
    BooleanTypeHandler java.lang.Boolean, boolean 数据库兼容的 BOOLEAN
    ByteTypeHandler java.lang.Byte, byte 数据库兼容的 NUMERIC 或 BYTE
    ShortTypeHandler java.lang.Short, short 数据库兼容的 NUMERIC 或 SMALLINT
    IntegerTypeHandler java.lang.Integer, int 数据库兼容的 NUMERIC 或 INTEGER
    LongTypeHandler java.lang.Long, long 数据库兼容的 NUMERIC 或 BIGINT
    FloatTypeHandler java.lang.Float, float 数据库兼容的 NUMERIC 或 FLOAT
    DoubleTypeHandler java.lang.Double, double 数据库兼容的 NUMERIC 或 DOUBLE
    BigDecimalTypeHandler java.math.BigDecimal 数据库兼容的 NUMERIC 或 DECIMAL
    StringTypeHandler java.lang.String CHAR, VARCHAR
    ClobReaderTypeHandler java.io.Reader -
    ClobTypeHandler java.lang.String CLOB, LONGVARCHAR
    NStringTypeHandler java.lang.String NVARCHAR, NCHAR
    NClobTypeHandler java.lang.String NCLOB
    BlobInputStreamTypeHandler java.io.InputStream -
    ByteArrayTypeHandler byte[] 数据库兼容的字节流类型
    BlobTypeHandler byte[] BLOB, LONGVARBINARY
    DateTypeHandler java.util.Date TIMESTAMP
    DateOnlyTypeHandler java.util.Date DATE
    TimeOnlyTypeHandler java.util.Date TIME
    SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
    SqlDateTypeHandler java.sql.Date DATE
    SqlTimeTypeHandler java.sql.Time TIME
    ObjectTypeHandler Any OTHER 或未指定类型
    EnumTypeHandler Enumeration Type VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
    EnumOrdinalTypeHandler Enumeration Type 任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。
    SqlxmlTypeHandler java.lang.String SQLXML
    InstantTypeHandler java.time.Instant TIMESTAMP
    LocalDateTimeTypeHandler java.time.LocalDateTime TIMESTAMP
    LocalDateTypeHandler java.time.LocalDate DATE
    LocalTimeTypeHandler java.time.LocalTime TIME
    OffsetDateTimeTypeHandler java.time.OffsetDateTime TIMESTAMP
    OffsetTimeTypeHandler java.time.OffsetTime TIME
    ZonedDateTimeTypeHandler java.time.ZonedDateTime TIMESTAMP
    YearTypeHandler java.time.Year INTEGER
    MonthTypeHandler java.time.Month INTEGER
    YearMonthTypeHandler java.time.YearMonth VARCHAR 或 LONGVARCHAR
    JapaneseDateTypeHandler java.time.chrono.JapaneseDate DATE
  • MyBatis 框架所提供的 这些类型处理器不能够满足需求时,还可以通过自定义 的方式对类型处理器进行扩展 ( 自定义类型处理器 可以通过实现TypeHandler 接口 或者 继承 BaseTypeHandle类来定义)。

    <typeHandler> 元素 就是用于在配置文件注册自定义类型处理器 的。它的使用方式有两种

    注册一个类类型处理器

    注册一个包所有类型处理器

    CustomertypeHandler.java

    java 复制代码
    package com.myh.type;
    
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.TypeHandler;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    public class CustomertypeHandler implements TypeHandler {
        @Override
        public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        } 
    
        @Override
        public Object getResult(ResultSet rs, String columnName) throws SQLException {
            return null;
        }
    
        @Override
        public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
            return null;
        }
    
        @Override
        public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
            return null;
        }
    }

    mybatis-config.xml

    xml 复制代码
         <!-- 注册一个类的类型处理器 -->
        <typeHandlers>
            <!--  以单个类的形式配置   -->
            <typeHandler handler="com.myh.type.CustomertypeHandler"/>
        </typeHandlers>
    
        <!-- 注册一个包中所有类的类型处理器 -->
         <typeHandlers>
             <!--  注册一个包中所有的typeHandler,系统在启动时会自动扫描包下的所有文件  -->
            <package name="com.myh.type"/>
        </typeHandlers>
<objectFactory>元素
  • MyBatis 框架每次创建 结果对象新实例 时,都会使用一个对象工厂 ( ObjectFactory )的实例来完成。MyBatis中默认的 ObjectFactory的作用 就是 实例化目标类,它既可以通过++默认构造方法实例化++ ,也可以在参数映射存在的时候通过++参数构造方法来实例化++。

  • 在通常情况下, 我们使用默认的ObjectFactory即可,MyBatis 中默认ObjectFactory 是由org.apache.ibatis rflection.factory.DefaultObjectFactory来提供服务的。大部分场景下都不用配置和修改,但如果想覆盖ObjectFactory的默认行为,则可以通过自定义ObjectFactory来实现。

    MyObjectFactory.java

    java 复制代码
    package com.myh.objFactory;
    
    import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
    
    import java.util.List;
    import java.util.Properties;
    
    //自定义工厂类 : 该类可以实现ObjectFactory接口 或 继承 DefaultObjectFactory类
    public class MyObjectFactory extends DefaultObjectFactory { //要继承DefaultObjectFactory类
    
        private static final long serialVerSionUID = -4114845625429965832L;
    
    
        @Override
        public <T> T create(Class<T> type) {
            return super.create(type);
        }
    
        @Override
        public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
            return super.create(type, constructorArgTypes, constructorArgs);
        }
    
        @Override
        public void setProperties(Properties properties) {
            super.setProperties(properties);
        }
    
        @Override
        public <T> boolean isCollection(Class<T> type) {
            return super.isCollection(type);
        }
    }

    mybatis-config.xml

    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>
    
        <objectFactory type="com.myh.objFactory.MyObjectFactory">
            <property name="name" value="MyObjectFactory"/>
        </objectFactory>
    
    </configuration>
<plugins>元素
  • MyBatis 允许在已映射语句执行过程中某一点 进行拦截调用 ,这种拦截调用 是通过插件 来实现的。<plugins> 元素作用 就是配置用户所开发插件。如果用户想要进行插件开发 ,必须要先了解其内部运行原理,因为在试图修改或重写已有方法的行为时,很可能会破坏MyBatis原 有的核心模块。
<environments>元素
  • 配置文件 中,<environments>元素 用于对环境 进行配置MyBatis环境配置 实际上就是 数据源的配置,我们可以通过 <environments>元素 配置多种数据源 ,即配置多种数据库

    xml 复制代码
       <!-- environments属性 -->
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--
                    通过"properties属性"来将 以下的driver、url、username、password 和
                    .properties配置文件 中的数据进行"动态替换"
                    -->
                    <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>

    在上述代码中,<environments>元素环境配置根元素,它包含个一default属性 ,该属性用于指定默认环境ID 。 是 <environments>元素的 "子元素", : <environment> 可以定义多个,其记属性用于表示所定义环境ID值 。在 environment元素内,包含事务管理 ( transactionManager ) 和 数据源 ( dataSource ) 的配置信息 ,其 <transactionManager>元素 用于配置事务管理 ,它的type 属性用于指定事务管理 的方式,即使用哪种事务管理器<dalaSource>元素 用于配置数据源 ,它的type属性 用于指定使用哪种数据源

    在MyBatis中,可以配置两种 类型的事务管理器,分别是 JDBCMANAGEDJDBC : 此配置直接使用了JDBC提交回滚设置 ,它依赖于从数据源 得到的连接来管理事务作用域
    MANAGED : 此配置从来不提交回滚 一个连接 ,而是让容器来管理事务整个生命周期

    默认情况 下,它会关闭连接 ,但一些容器并不希望这样,为此可以将closeConnection属性

    置为false阻止它默认关闭行为

    ps :

    如果没有必要中 使用的是 Spring+ MyBatis,则 没有必要 在MyBatis ( mybatis-config.xml ) 中 配置事务管理器,因为实际开发中 ,会使用Spring 自带的管理器实现事务管理

<mappers>元素
  • 配置文件 ( mybatis-config.xml )中,<mappers>元素 用于 指定MyBatis 映射文件 (引入"映射文件 ")(XxxMapper.xml )的 位置,一般可以使用以下 4种方法 引入映射文件 。 ( 一个mybatis-config.xml 配置文件 可以引入多个"映射文件"。)

    使用 "类路径" 引入
    使用 "本地文件路径" 引入
    使用 "接口类" 引入
    使用 "包名" 引入

  • 使用 "类路径" 引入

    xml 复制代码
    <mappers>
            <!-- 使用"类路径"读取"映射文件" -->
            <mapper resource="com/myh/mapper/CustomerMapper.xml"/>
    </mappers>
  • 使用 "本地文件路径" 引入

    xml 复制代码
     <mappers>
            <!--  使用"本地文件路径"引入"映射文件"  -->
            <mapper url="file:///D:/com/myh/mapper/CustomerMapper.xml"/>
     </mappers>
  • 使用 "接口类" 引入

    xml 复制代码
    <mappers>
            <!--  使用"接口类"引入"映射文件"  -->
            <mapper class="com.myh.mapper.CustomerMapper"/>
    </mappers>
  • 使用 "包名" 引入

    xml 复制代码
    <mappers>
            <!-- 使用"包名"引入"映射文件" -->
          <package name="com.myh.mapper"/>
    </mappers>

三、MyBatis的 "映射文件"

  • 映射文件 ( XxxMapper.xml )是Mybatis 框架中十分重要的文件,可以说,Mybatis框架的强大之处 就体现在"映射文件"的编写上。
  • 映射文件 中,<mapper>元素映射文件根元素 ,其他元素都是它的子元素

"配置文件"中的 "主要元素"

<select>元素
  • <select>元素 用于映射 "查询语句 ",它可以帮助我们从数据库中读出数据,并组装数据给企业开发者。

    xml 复制代码
        <!-- "查询数据"-->
    	<select id="findCustomerById" parameterType="Integer" resultType="com.myh.po.Customer">
             select * from t_customer where id = #{id}
        </select>

    上述语句中的唯一标识为 findCustomerByld,它接收 一个 Integer 类型参数 ,并返回 一个Customer类型对象

  • <select>元素 中,除了 上述代码中的几个属性外,还有其他一些可以配置属性如下所示

    属性 说明
    id 表示命名空间中唯一标识符 , 常与命名空间组合起来使用组合后如果不唯一, MyBatis会抛出异常。
    parameterType 该属性表示传入SQL语句参数类全限定名 或者别名 。它是一个可选属性, 因为MyBatis 可以通过TypeHandler 推断出具体传入语句参数 。其默认值是unset (依赖于驱动)
    resultType 从SQL语句中返回的类型全限定名 或者别名 。如果是集合类型 ,那么返回的应该是集合可以包含类型 ,而不是集合本身 。返回时可以使用resultTyperesultMap之一。
    resultMap 表示外部resultMap命名引用 。返回时可以使用resultTyperesultMap之一。
    flushCache 表示在调用SQL语句 之后,是否需要MyBatis清空之前查询本地缓存二级缓存 。其值为布尔类型( truelfalse),默认值为false 。如果设置为true ,则任何时候只要SQL语句被调用,都会清空本地缓存二级缓存。
    useCache 用于控制二级缓存开启关闭 。其值为布尔类型( truelfalse),默认值为true ,表示将查询结果 存入二级缓存中。
    timeout 用于设置超时参数 ,单位为超时将抛出异常
    fetchSize 获取记录总条数设定 ,其默认值是unset (依赖于驱动)。
    statementType 用于设置MyBatis 使用哪个JDBCStatement 工作,其值为STATEMENTPREPARED(默认值)CALLABLE , 分别对应JDBC中的StatementPreparedStatementCallableStatement
    属性 说明
    resultSetType 表示结果集类型 ,其值可设置为FORWARD_ONLY、SCROLL_SENSITIVE 或SCROLL_INSENSITIVE, 它的默认值是unset (依赖于驱动)
<insert>元素
  • <insert>元素 用于映射"插入语句",在执行完 元素中定义的SQL语句 后,会返回 一个表示插入记录数整数
xml 复制代码
<!--
   useGeneratedKeys="true" : 获得该insert语句插入数据库时形成的"主键id" / 获得数据库内部产生的主键id
   keyProperty="id" : 将插入或更新时的"返回值"赋值到PO类的对应的"属性"上 : 即将刚获得的"主键id"赋值到PO类对应的id属性上
   -->
<!--  该insert语句的返回值 : ①返回插入成功的行数 ②插入行的主键id  -->
<insert id="addCustomer" parameterType="com.myh.po.Customer"
        flushCache="true" statementType="PREPARED"
        keyProperty="id" keyColumn="" useGeneratedKeys="true" timeout="20">
    insert into t_customer(username,jobs,phone)
    values(#{username},#{jobs},#{phone})
</insert>

以上的 insert语句返回值 : ①返回插入成功的行数 ②插入行的主键id

上述代码 中可以看出,<insert>元素属性<select>元素属性大部分相同<insert>元素 包含了 3个特有属性

  • <insert>元素 中的三个特有 属性 :
属性 说明
keyProperty ( 仅对insert和update有用 )此属性 ( keyProperty )的作用 是将插入 或 更新操作时返回值赋值给 PO类某个属性,通常会设置为"主键 "对应的属性。 (通常会设置该属性的值 为"id" (即将插入形成的"主键id "值赋值到PO类 中 )。如果需要设置联合主键 ,可以在多个值 之间用逗号隔开例子如 : keyProperty ="i'd" ( 要结合useGeneratedKeys 属性使用 ) : 将useGeneratedKeys 属性获得的 ( 插入形成的 ) "主键id " 赋值到PO类 的对应的id属性 上,这样就能获得insert语句 生成的数据对应 的"主键id"了。
keyColumn ( 仅对insertupdate 有用 ) 此属性用于 设置第几列主键,当主键列不是表中第一列时需要设置,在需要主键联合 时,值可以使用逗号隔开。
useGeneratedKeys ( 仅对insertupdate 有用 )此属性会使 MyBatis 使用 JDBCgetGeneratedKeys( ) 方法来获取由数据库内部生产主键 (此时一般配合keyProperty 属性使用来将该"主键 赋值给PO类 对应的属性 上。"), 如MySQLSQL Server自动递增字段 ,其 默认值false

执行插入操作 后,很多时候我们会需要返回插入成功数据生成主键值 ( 表中主键id ),此时就可以通过
上面所讲解的3个属性来实现。


  • 如果使用的数据库支持主键自动增长 (如MySQL ),那么可以通过keyProperty属性 指定PO类某个属性接收主键返回值 ( 通常会设置到id属性上 : 将主键id 赋值给PO类id属性 上 ),同时还要通过 useGeneratedKeys 属性才能实现目标功能。 例子如下 :

<insert>元素 中的三个特有 属性 例子如 :

CustomerMapper.xml (映射文件) :

xml 复制代码
<!--
   useGeneratedKeys="true" : 获得该insert语句插入数据库时形成的"主键id" / 获得数据库内部产生的主键id
   keyProperty="id" : 将插入或更新时的"返回值"赋值到PO类的对应的"属性"上 : 即将刚获得的"主键id"赋值到PO类对应的id属性上
   -->
<!--  该insert语句的返回值 : ①返回插入成功的行数 ②插入行的主键id  -->
<insert id="addCustomer" parameterType="com.myh.po.Customer"
        keyProperty="id"  useGeneratedKeys="true" >
    insert into t_customer(username,jobs,phone)
    values(#{username},#{jobs},#{phone})
</insert>

以上的 insert语句返回值 : ①返回插入成功的行数 ②插入行的主键id

CustomerTest.java (测试类) :

java 复制代码
public class CustomerTest {

 @org.junit.Test //单元测试
 public void addCustomerTest() throws IOException {
     //1.读取mybatis框架的配置文件
     String resource = "com/myh/映射文件的元素/mybatis-config.xml";
     //通过"输入流"读取mybatis配置文件
     /*
        在该mybatis-config.xml配置文件中,已配置了"数据源"信息 和配置了"映射文件 : XxxMapper.xml"的位置,
        可实施加载"映射文件"
      */
     InputStream inputStream = Resources.getResourceAsStream(resource);

     //2.根据配置文件"构建会话工厂 : SqlSessionFactory "
     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
     //3.通过SqlSessionFactory(会话工厂)创建SqlSession("会话"对象)
     SqlSession sqlSession = sqlSessionFactory.openSession();

     Customer customer = new Customer();
     customer.setUsername("小蓝");
     customer.setJobs("学生");
     customer.setPhone("12345678");
     //将该Customer对象存入到数据库中,同时目的是: 将存入到数据库中的数据对应的"主键id"获得且返回
     int insert = sqlSession.insert("CustomerMapper.addCustomer", customer);
     /**
         * 输出"插入数据"形成的"主键id值"  (从数据库中获得的主键id值是存储在Customer这个PO类中的)
      */
     System.out.println(customer.getId());
     if (insert > 0) {
         System.out.println("你成功插入了" + insert + "条数据!");
     } else {
         System.out.println("插入数据操作失败! ");
     }
     //4.设置"事务管理"
     sqlSession.commit();
     //5.关闭SqlSession
     sqlSession.close();
 }
}

通过上述的<insert>元素三个特有属性 ,即可获得插入数据对应" 主键id"


  • 如果使用的数据库不支持主键自动增长 (如Oracle ), 或者支持增长的数据库 取消了主键自增 的规则时,也可以使用MyBatis 提供的另一种方式自定义生成主键例子如下

    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">
    <!--
       映射文件中,插入数据用 <insert>元素
    -->
    <!-- #{} : 相当于"占位符"  ${} : 相当于在sql语句后要拼接的"字符串" -->
    <mapper namespace="CustomerMapper">
    
        <insert id="insertCustomer" parameterType="com.myh.po.Customer">
             <selectKey keyProperty="id" resultType="Integer" order="BEFORE">
           select if(max(id) is null,1,max(id) + 1)as newId from t_customer
             </selectKey>
            insert into t_customer(username,jobs,phone)
            values(#{username},#{jobs},#{phone})
        </insert>
      
    </mapper>

    上述代码中,<selectKey> 元素会首先运行 ,它会通过自定义的语句 来设置数据 中的主键 (如果

    t_customer表中没有记录 ,则将id设置为1 ,否则就将id的最大值加1 ,来为新的主键),然后再调用插入语句
    <selectKey>元素 在使用时可以设置以下几种属性

    xml 复制代码
    <selectKey
       keyProperty="id"
       resultType="Integer"
       order="BEFORE"
       statementType="PREPARED">

    在上述 <selectKey>元素 的几个属性中,keyPropertyresultTypestatementType 的作用与前面讲解的相同,order 属性 可以被设置为BEFOREAFTER如果设置BEFORE,那么它会首先执行 <selectKey>元素 中的配置设置主键 ,然后执行插入语句 ;如果设置为AFTER ,那么它会先执行插入语句 ,然后执行 <selectKey>元素中的配置内容。

<update>元素和<delete>元素
  • <update><delete>元素 的使用比较简单,它们的属性配置也基本相同 ,其常用属性如下 :
xml 复制代码
  <!-- 更新 -->
   <update id="updateCustomer" parameterType="com.myh.po.Customer"
           flushCache="true" statementType="PREPARED" timeout="20">
   </update>

   <!-- 删除 -->
   <delete id="deleteCustomer" parameterType="com.myh.po.Customer"
           flushCache="true" statementType="PREPARED" timeout="20">
   </delete>

从上述配置代码中可以看出,<update><delete>元素属性 基本与 <select>元素中属性一致

<insert>元素 一样,<update> 和<delete>元素在执行完之后 ,也会返回一个表示影响记录条数整数,其使用示例如下 :

xml 复制代码
<!-- 更新 -->
<update id="updateCustomer" parameterType="com.myh.po.Customer">
       update t_customer set username = #{username},jobs=#{jobs},phone=#{phone}
       where id = #{id}
   </update>

 <!-- 删除 -->
 <delete id="deleteCustomer" parameterType="Integer">
      delete from t_customer where id = #{id}
   </delete>
<sql>元素
  • 一个映射文件 中,通常需要定义多条SQL语句 ,这些SQL语句的组成 可能有一部分是相同的 ( 如多条select语句 中都查询相同的idusernamejobs 字段 ),如果每一个SQL语句都重写遍相同的部分 , 势必会增加代码量,导致映射文件过于臃肿

  • 那么有没有什么办法将这些SQL语句相同组成部分抽取出来,然后在需要的地方引用呢 ?

    答案是肯定的,我们可以在映射文件 中使用MyBatis 所提供的 <sql>元素 来解决上述问题。<sql>元素的作用 : 就是定义可重用SQL代码片段,然后在其他语句中引用 这一代码片段

    例子如

    xml 复制代码
     <sql id="customerColumns"> id,username,jobs,phone</sql>
    
     <select id="findCustomerById" parameterType="Integer" resultType="com.myh.po.Customer">
            select <include refid="customerColumns"/>
            from t_customer
            where id = #{id}
     </select>
<resultMap>元素 (可解决"属性名" 和 "字段名"不一样导致的数据无法映射成功的问题)
  • <resultMap>元素 表示结果映射集,是 MyBatis最重要 也是 最强大元素。它的主要作用 : 是
    定义映射规则级联的更新 以及 定义类型转化器 等。

    ps :
    <resultMap>元素 可解决"属性名 " 和 "字段名 " 不一样导致 的数据无法映射成功问题

  • <resutMap>元素 中包含了属性 / 子元素,如下所示 :

    xml 复制代码
       <!--  resultMap的元素结构  -->
       <resultMap type="" id="">
    
           <constructor>  <!-- 类在实例时,用来注入"结果"到"结构方法"中 -->
              <idArg/>    <!-- ID参数;标记结果为ID -->
               <arg/>     <!-- 注入到构造方法的一个普通结果 -->
           </constructor>
    
           <id/>          <!-- 用于表示哪个"列"是"主键" -->
           <result/>      <!-- 注入到"字段"或"JavaBean属性"的普通结果 -->
           <association property=""/>  <!-- 用于一对一关联 -->
           <collection property=""/>   <!-- 用于一对多关联 -->
    
           <discriminator javaType="">   <!-- 使用"结果值"来决定哪个"结果映射"-->
               <case value=""></case>
           </discriminator>
    
       </resultMap>
  • <resutMap>元素属性 关系如下表所示 :

    属性 描述
    type 表示需要 映射 POJO ( 普通Java对象 )
    id 这个 resultMap唯一标识
  • <resutMap>元素子元素 关系如下表所示 :

    子元素 描述
    <constructor> 用于配置构造方法 ( 当一个POJO未定义无参构造方法 时,就可以使用 <constructor>元素 进行配置)。
    <id> 分别标记 POJO中属性 中的"主键 "和 标记数据库表中字段 的 "主键",并 将二者进行关联ps : 这意味着,通过 <resultMap> 中的 <id>元素 的配置,POJO"主键"属性名 不用 和数据库中 "主键"名相同。
    <result> 表示 POJO 中 "属性 "和 数据库表映射关系。(用于将 POJO 中 "属性 "和 数据库表 中的 " "进行关联。 ) ps : 这意味着,通过 <resultMap> 中的 <result>元素 的配置,数据库 中的 "字段 " 以及 该"字段 "相对应的 "属性 "名,不用一致。(在 <result>中设置各自的名称即可)
    <association> 表示"一对一"关联。用于处理"多表 "时的关联关系
    <collection> 表示"一对多"关联。用于处理"多表 "时的关联关系
    <discriminator> 使用"结果值 "来决定 哪个"结果映射"。用于处理 一个单独的数据库查询 返回很多不同数据类型 结果集情况
  • 在默认情况下,MyBatis 程序在运行时会 自动地将查询到数据 与需要返回的对象属性 进行匹配赋值 ( 需要表中的 列名 与对象的属性名称完全一致 )。 然而实际开发时,数据表中的 和需要返回的对象的属性 可能不会完全一致, 这种情况下 MyBatis是不会自动赋值的。此时,就可以使用 <resultMap>元素进行处理。

  • 实际开发中,如果当POJO中"属性名 " 和 数据库中"字段名 " 不一致,此时查询数据库,数据会无法映射到POJO类中,最后导致查询到的内容为null 。 此时用 <resultMap>元素即可解决这个问题。

    例子如 :


    此时可使用"映射文件 " 中的因属性名 和 字段名不一致导致的数据无法映射POJO 中的问题。如下所示 :

    UserMapper.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="UserMapper">
    
        <!--  select元素中使用resultType时,当数据库中"字段名" 和POJO中"属性名"不一致时,select的数据将则无法映射到POJO类中,即输出内容为null -->
        <!--  select元素中用resultMap时,数据库中"字段名" 和 POJO中"属性名"不用保持一致,此时也能完成将select到的数据映射到POJO类中-->
       <select id="selectUser_resultType" resultType="com.myh.po.User" parameterType="Integer">
           select * from t_user where t_id = #{id}
       </select>
    
    
        <!--
        上面这个select的查询的数据是无法映射到POJO类中,即select的数据为null,因为数据库中"字段名" 和 POJO中的"属性名",
        此时可用 <resultMap>元素来解决这个问题 -->
        <resultMap id="resultMap" type="com.myh.po.User">
            <!--   下面配置的目的 : "属性名" 和 "字段名" 可以不用保持一致   -->
            <id property="id" column="t_id"/>
            <result property="name" column="t_name"/>
            <result property="age" column="t_age"/>
        </resultMap>
    
        <!--  因为此处用了resultMap(已经配置好了,完成各种内容的"映射了",所以即使"属性名" 和 "字段名"不一致,也能select到数据)  -->
        <select id="selectUser_resultMap" resultMap="resultMap" parameterType="Integer">
            select * from t_user where t_id = #{id}
        </select>
    
    </mapper>

    UserTest.java (测试类)

    java 复制代码
    public class UserTest {
    
        @org.junit.Test //单元测试
        public void selectUser_resultType_resultMap_Test() throws IOException {
            //1.读取mybatis框架的配置文件
            String resource = "com/myh/映射文件的元素/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //2.根据配置文件"构建会话工厂 : SqlSessionFactory "
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //3.通过SqlSessionFactory(会话工厂)创建SqlSession("会话"对象)
            SqlSession sqlSession = sqlSessionFactory.openSession();
             User user1 = (User)sqlSession.selectOne("UserMapper.selectUser_resultType", 2);
            /**
               此处输出的内容为 : null ,因为字段名和属性名 不一样,数据无法映射成功,最后输出的内容为 : null
             */
            System.out.println("从数据库中查询到的数据为(通过resultType获得): "+user1);
    
            /**
             此处输出的内容为 : "查询到的数据",即使"属性名" 和 "字段名"没有保持一致,但通过resultMap元素的配置,查询到的数据依然能
              映射到POJO类中。
             */
            User user2 = (User)sqlSession.selectOne("UserMapper.selectUser_resultMap", 2);
            System.out.println("从数据库中查询到的数据为(通过resultMap获得): "+user2);
    
            //4.关闭SqlSession
            sqlSession.close();
        }
    }

    控制台输出结果为

相关推荐
刘大浪31 分钟前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
蓝染-惣右介2 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
武子康3 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
一二小选手3 小时前
【Mybatis】@Param注解 resultMap手动映射
java·mybatis
郑祎亦6 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
jokerest12320 小时前
web——sqliabs靶场——第十三关——报错注入+布尔盲注
mybatis
武子康20 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
WindFutrue1 天前
使用Mybatis向Mysql中的插入Point类型的数据全方位解析
数据库·mysql·mybatis
AiFlutter1 天前
Java实现简单的搜索引擎
java·搜索引擎·mybatis