MyBatis再攻读之MyBatis.

一、框架基本介绍

1、概念

支撑一般SQL查询、存储进度和高档映射,简化和促成了Java
数据持久化层的的开源框架,主要流行的原因在于她的简单性和易使用性。

2、特点

持之以恒层 、ORM(对象关系映射) 、轻量级、协助SQL语句。

3、工作规律

  • 应用程序读取mybatis的安顿文件,形成布局对象。
  • 透过sqlsessionfactorybuilder读取配置对象,发生sqlsessionfactory
  • 通过sqlsessionfactory得到sqlsession
  • 通过sqlsession得到mapper映射器
  • 通过mapper读取对应的炫耀文件从而操作数据库
  • 处负责人务
  • 释放sqlsession

二、配置文件含义

1、environment   

MyBatis 1MyBatis 2

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/test" />
                <property name="username" value="root" />
                <property name="password" value="admin" />
            </dataSource>
        </environment>
        <environment id="test">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="JNDI">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/test" />
                <property name="username" value="root" />
                <property name="password" value="admin" />
            </dataSource>
        </environment>
    </environments>

View Code

 紧要用于配置三个dataSource环境;在同一个条件中切换分化的dataSource时,需要为各类数据库创设一个SqlSessionFactory。对于每个环境
environment,大家需求配置 dataSource 和 transactionManager。

1.1 DateSource
  • UNPOOLED:为每一个数据库操作创设一个新的接连,使用落成就关门他。该办法适用于小范围数据的产出用户的简要应用程序上。
  • POOLED:Mybatis会创设一个数据库连接池,连接池中的一个延续将会被看成数据库操作。一旦数据库操作完结,MyBatis
    会将此三番五次再次来到给连接池。
  • JNDI:MyBatis
    从在应用服务器向配置好的 JNDI 数据源 dataSource
    获取数据库连接。
1.2 TransactionManager
  • JDBC:应用程序自己管总管务(汤姆cat)
  • MANAGED:应用本身不去管理业务,而把事务管理交给应用所在的服务器举行管理。(JBoss、WebLogic、GlassFish)

2、properties

MyBatis 3MyBatis 4

<properties resource="application.properties">
<property name="jdbc.username" value="db_user" />
<property name="jdbc.password" value="verysecurepwd" />
</properties>

View Code

那边,借使 application.properties
文件包罗值 jdbc.username 和 jdbc.password,则上述定义的 username
和password 的值 db_user 和 verysecurepwd 将会被 application.properties
中定义的附和的 jdbc.username 和jdbc.password 值覆盖。

3、typeAliases

假定没有设置typeAliases的类型别名,对于resultType和parameterType属性值,我们须要拔取JavaBean的通通限定名。所以,大家可以为完全限定名使用别名,通过typeAliases设置:

3.1 为各类JavaBean单独起别名

MyBatis 5MyBatis 6

<typeAliases>
<typeAlias alias="Student" type="com.mybatis3.domain.Student" />
<typeAlias alias="Tutor" type="com.mybatis3.domain.Tutor" />
</typeAliases>

View Code

3.2 为JavaBean 所在的包起别名

理所当然也能够毫不为每一个JavaBean
单独定义别名,你可以为提供须求起别名的JavaBean
所在的包,Mybatis会自动扫描包内定义的JavaBeans,然后分别为JavaBean注册一个小写字母起首的非完全限定的类名格局的别名。

MyBatis 7MyBatis 8

<typeAliases>
<package name="com.mybatis3.domain" />
</typeAliases>

View Code

要是 Student.java 和 Tutor.java 的 Bean
定义在 com.mybatis3.domain 包中,则
com.mybatis3.domain.Student的别名会被登记为 student。而
com.mybatis3.domain.Tutor 别名将会被登记为 tutor。

 3.3 利用注明的法子起别名

行使注明@Alias起别名,@Alias
申明将会覆盖配置文件中的<typeAliases>定义:

MyBatis 9MyBatis 10

@Alias("StudentAlias")
public class Student
{ }

View Code

4、typeHandlers

MyBatis
对于以下的品类应用内建的品类处理器:所有的大旨数据类型、基本项目标包裹档次、
byte[]、java.util.Date、 java.sql.Date、 java,sql.提姆e、
java.sql.提姆estamp、 java 枚举类型等。所以当 MyBatis
发现属性的系列属于上述项目,他会利用相应的品类处理器将值设置到PreparedStatement
中,同样地,当从 SQL 结果集打造 JavaBean 时,也有类似的长河。

假设,大家可以自定义一个类型处理器为我们子定义的Class服务。一旦大家完成了自定义的品类处理器,大家必要在
mybatis-config.xml 中注册它:

MyBatis 11MyBatis 12

 */
public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber> {
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, PhoneNumber phoneNumber, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i, phoneNumber.toString());
    }

    public PhoneNumber getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return new PhoneNumber(resultSet.getString(s));
    }

    public PhoneNumber getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return new PhoneNumber(resultSet.getString(i));
    }

    public PhoneNumber getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return new PhoneNumber(callableStatement.getString(i));
    }
    }

自定义类型处理器 

MyBatis 13MyBatis 14

    <typeHandlers>
        <typeHandler handler="com.summersoft.ts.util.PhoneTypeHandler"/>
    </typeHandlers>

注册自定义类型处理器

 时间类型:Mybatis 会将java.util.Data
类型转换成java.sql.提姆estamp(时间戳)并安装。

5、Mappers

MyBatis 15MyBatis 16

<mappers>
  <mapper resource="com/mybatis3/mappers/StudentMapper.xml" />
  <mapper url="file:///D:/mybatisdemo/app/mappers/TutorMapper.xml" />
  <mapper class="com.mybatis3.mappers.TutorMapper" />
  <package name="com.mybatis3.mappers" />
</mappers>

View Code

  • resource 属性用来指定在 classpath 中的 mapper 文件。
  • url 属性用来经过一点一滴文件系统路径或者 web URL 地址来指向 mapper 文件
  • class 属性用来针对一个 mapper 接口
  • package 属性用来指向可以找到 Mapper 接口的包名

6、Settings

那是 MyBatis 中极为紧要的调整设置,它们会变动 MyBatis
的运转时作为。下表描述了安装中各队的意向、默许值等。

设置参数 描述 有效值 默认值
cacheEnabled 该配置影响的所有映射器中配置的缓存的全局开关。 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods). true | false false (true in ≤3.4.1)
multipleResultSetsEnabled 是否允许单一语句返回多结果集(需要兼容驱动)。 true | false true
useColumnLabel 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 true | false true
useGeneratedKeys 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 true | false False
autoMappingBehavior 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 指定发现自动映射目标未知列(或者未知属性类型)的行为。

    • NONE: 不做任何反应
    • WARNING: 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'的日志等级必须设置为 WARN)
    • FAILING: 映射失败 (抛出 SqlSessionException)
NONE, WARNING, FAILING NONE
defaultExecutorType 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数。 任意正整数 Not Set (null)
defaultFetchSize 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 任意正整数 Not Set (null)
safeRowBoundsEnabled 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。 true | false False
safeResultHandlerEnabled 允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为false。 true | false True
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 true | false False
localCacheScope MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 SESSION | STATEMENT SESSION
jdbcTypeForNull 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods 指定哪个对象的方法触发一次延迟加载。 A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage 指定动态 SQL 生成的默认语言。 A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler Specifies the TypeHandler used by default for Enum. (Since: 3.4.5) A type alias or fully qualified class name. org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 true | false false
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始) true | false false
logPrefix 指定 MyBatis 增加到日志名称的前缀。 Any String Not set
logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
proxyFactory 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 or above)
vfsImpl 指定VFS的实现 自定义VFS的实现的类全限定名,以逗号分隔。 Not set
useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始) true | false true
configurationFactory 指定一个提供Configuration实例的类. 这个被返回的Configuration实例是用来加载被反序列化对象的懒加载属性值. 这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始) 类型别名或者全类名. Not set

三、映射文件讲解

 
大家因此映射器配置文件配置了映射语句,同时创造一个截然对应的一个映射器接口。接口名跟配置文件名相同。接口所在包名也跟配置文件所在包名完全一
样。在布局文件中,其命名空间namespace 应该和接口的完全限定名保持一致。

1、INSERT

id: 对应接口的方法名
parameterType: 输入参数
useGeneratedKeys=”true” :让数据库生成自拉长的列
keyProperty=”属性名”: 将生成的值设置到中间一个输入对象属性内

如要是Oracle数据库,没有像MySQL那样的自增机制:

MyBatis 17MyBatis 18

    <insert id="insertStudent" parameterType="Student">
        <selectKey keyProperty="studId" resultType="int" order="BEFORE">
            SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL
        </selectKey>
        INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
        VALUES(#{studId},#{name},#{email},#{phone})
    </insert>

View Code

order=”BEFORE” 表示在插入语句暴发前发生studId的值就赋给插入语句。

MyBatis 19MyBatis 20

    <insert id="insertStudent" parameterType="Student">
        INSERT INTO STUDENTS(NAME,EMAIL, PHONE)
        VALUES(#{name},#{email},#{phone})
        <selectKey keyProperty="studId" resultType="int" order="AFTER">
            SELECT ELEARNING.STUD_ID_SEQ.CURRVAL FROM DUAL
        </selectKey>
    </insert>

View Code

 order=”AFTER” 表示在插入语句之后选用触发器(trigger)来安装主键值

2、SELECT

2.1、 resultType=’Student’ 当
column名和对象property名一致时,会自行把相应的column填充上对象的property,假如查询记录再次来到多条,Mybatis
自动用 集合类来接纳。

2.2、Mybatis根据集合的门类,会利用适当的汇集完毕:

对于 List,Collection,Iterable
类型,MyBatis 将返回 java.util.ArrayList
对于 Map 类型,MyBatis 将返回
java.util.HashMap
对于 Set 类型,MyBatis 将返回
java.util.HashSet
对于 SortedSet 类型,MyBatis 将返回
java.util.TreeSet

2.3、ResultType 和 ResuleMap 无法而且利用,ResultMap的 id
在此命名空间内是绝无仅有的 

2.4、Resulttype=”java.util.HashMap”。在那种气象下,结果集中的列名将会作为Map中的key值,而列值作值将会作为Map的value值。假诺查询记录再次回到多条,Mybatis自动用集合类来接受。

2.5、俺们得以从此外一个<resultMap>,扩充出一个新的<resultMap>,那样原本的属性值可以伸张过来

2.6、一对一关联查询

MyBatis 21MyBatis 22

   <resultMap type="Student" id="StudentWithAddressResult">
        <id property="studId" column="stud_id" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <result property="phone" column="phone" />
        <result property="address.addrId" column="addr_id" />
        <result property="address.street" column="street" />
        <result property="address.city" column="city" />
        <result property="address.state" column="state" />
        <result property="address.zip" column="zip" />
        <result property="address.country" column="country" />
    </resultMap>

一对一直接涉及

MyBatis 23MyBatis 24

  <resultMap type="Address" id="AddressResult">
        <id property="addrId" column="addr_id" />
        <result property="street" column="street" />
        <result property="city" column="city" />
        <result property="state" column="state" />
        <result property="zip" column="zip" />
        <result property="country" column="country" />
    </resultMap>
    <resultMap type="Student" id="StudentWithAddressResultIn">
        <id property="studId" column="stud_id" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <association property="address" resultMap="AddressResult" />
    </resultMap>

一对一嵌套提到

MyBatis 25MyBatis 26

  <resultMap type="Student" id="StudentWithAddressResultHasOne">
        <id property="studId" column="stud_id" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <association property="address" javaType="Address">
            <id property="addrId" column="addr_id" />
            <result property="street" column="street" />
            <result property="city" column="city" />
            <result property="state" column="state" />
            <result property="zip" column="zip" />
            <result property="country" column="country" />
        </association>
    </resultMap>

一对一内联关联has one

2.7、一对多涉及查询

MyBatis 27MyBatis 28

    <resultMap type="Course" id="CourseResult">
        <id column="course_id" property="courseId" />
        <result column="name" property="name" />
        <result column="description" property="description" />
        <result column="start_date" property="startDate" />
        <result column="end_date" property="endDate" />
    </resultMap>
    <resultMap type="Tutor" id="TutorResult">
        <id column="tutor_id" property="tutorId" />
        <result column="tutor_name" property="name" />
        <result column="email" property="email" />
        <collection property="courses" resultMap="CourseResult" />
    </resultMap>

View Code

2.8、在MyBatis的安排文件中,能够不指定输入参数。而利用#{param1}和#{param2}引用接口中艺术的形参。

 3、动态SQL

3.1 if 条件

MyBatis 29MyBatis 30

    <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
          SELECT * FROM COURSES
          WHERE TUTOR_ID= #{tutorId}
          <if test="courseName != null">
              AND NAME LIKE #{courseName}
          </if>
          <if test="startDate != null">
              AND START_DATE > #{startDate}
          </if>
          <if test="endDate != null">
              AND END_DATE  &lt; #{endDate}
          </if>
     </select>

if 语句

3.2 choose when条件

MyBatis 31MyBatis 32

   <select id="searchCoursesTwo" parameterType="hashmap" resultMap="CourseResult">
        SELECT * FROM COURSES
        <choose>
            <when test="searchBy == 'Tutor'">
                WHERE TUTOR_ID= #{tutorId}
            </when>
            <when test="searchBy == 'CourseName'">
                WHERE name like #{courseName}
            </when>
            <otherwise>
                WHERE TUTOR start_date >= now()
            </otherwise>
        </choose>
    </select>

choose when 条件

<choose>测试条件的值,且使用第三个值为TRUE的子句,假若没有标准化为True,则运用<otherwise>内的词句

3.3 where 条件

MyBatis 33MyBatis 34

  <select id="searchCourses" parameterType="hashmap"
            resultMap="CourseResult">
        SELECT * FROM COURSES
        <where>
            <if test=" tutorId != null ">
                TUTOR_ID= #{tutorId}
            </if>
            <if test="courseName != null">
                AND name like #{courseName}
            </if>
            <if test="startDate != null">
                AND start_date >= #{startDate}
            </if>
            <if test="endDate != null">
                AND end_date  &lt;= #{endDate}
            </if>
        </where>
    </select>

Where 子句

<where>元素唯有在其间标签有再次来到内容时才会在动态语句上插入WHERE条件语句。并且,倘使Where子句以AND
或者 OR 打头,则打头的AND 或 OR 将会被移除。

3.4 trim 条件

MyBatis 35MyBatis 36

   <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
        SELECT * FROM COURSES
        <trim prefix="WHERE" prefixOverrides="AND | OR">
            /*拼接成的字句前面加上WHERE,如果WHERE后面有AND 或者 OR,将去掉。suffix末尾加上,suffixOverrides 末尾去掉*/
            <if test=" tutorId != null ">
                TUTOR_ID= #{tutorId}
            </if>
            <if test="courseName != null">
                AND name like #{courseName}
            </if>
        </trim>
    </select>

trim 子句

 <trim> 元素和
<where>元素看似,若是任意一个<if>条件为true,<trim>元素会插入WHERE,并且移除紧跟WHERE
前面的AND 或 OR

3.5 foreach 循环

MyBatis 37MyBatis 38

   <select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult">
        SELECT * FROM COURSES
        <if test="tutorIds != null">
            <where>
                <foreach item="tutorId" collection="tutorIds">
                    OR tutor_id=#{tutorId}
                </foreach>
            </where>
        </if>
    </select>

foreach子句

它可以迭代遍历一个数组或者列表,构造AND/OR条件照旧一个IN子句。

3.6 set 条件

MyBatis 39MyBatis 40

  <update id="updateStudent" parameterType="Student">
        update students
        <set>
            <if test="name != null">name=#{name},</if>
            <if test="email != null">email=#{email},</if>
            <if test="phone != null">phone=#{phone},</if>
        </set>
        where stud_id=#{id}
    </update>

set子句

若是<if>条件重回了其余公文内容,<set>将会插入set关键字和其文件内容。并且会去除末尾的”,”

 4、缓存

4.1、首先级缓存:假如您使用同一个SqlSession
接口对象调用了一致的SELECT语句,则直接会从缓存中回到结果,而不是再查询三次数据库。

4.2、其次级缓存:大家得以在SQL映射器XML配置文件中使用<cache
/>元素添加全局二级缓存。

    • 怀有的在映射语句文件定义的<select>语句的查询结果都会被缓存
    • 拥有的在映射语句文件定义的<insert>,<update>
      和<delete>语句将会刷新缓存
    • 缓存依据新近起码被接纳(Least
      Recently Used,LRU)算法管理
    • 缓存不会被其余形式的依照时间表的刷新(没有刷新时间距离),即不帮忙定时刷新机制
    • 缓存将积存 1024 个
      查询艺术重回的列表或者目的的引用
    • MyBatis,缓存是线程安全的

本来我们也可以 复写默许属性来自定义缓存的作为:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

eviction:LRU、FIFO、SOFT、WEAK
readOnly:一个只读的缓存会向调用者重回被缓存对象的一份引用。一个读/写缓存cache将会重回改目的的一份拷贝。

 

 

 

网站地图xml地图