MyBatis的体系结构和配置文件详解

一、SqlSessionFactory

MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的,它是单个数据库映射关系经过编译后的内存镜像;SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例,一般SqlSessionFactroy采用单例模式去创建。

SqlSessionFactory的一个重要作用就是创建SqlSession。

~SqlSession openSession() —— 创建SqlSession对象。

二、SqlSession

1.作用:SqlSession是执行持久化操作的对象,类似于JDBC的Connection。它是应用程序与持久存储层之间执行交互操作的一个单线程对象,SqlSession底层封装了JDBC连接,SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法,可以用它来直接执行已映射的Sql语句,并且每个线程有它自己独立的SqlSession实例。SqlSession的实例不能共享,也是线程不安全的。使用完SqlSession之后应关闭session。

2.常用方法:

~int insert(String statement) —— 插入方法,参数statement是在配置文件中定义的<insert>元素的id,返回执行sql语句所影响的行数。

~int insert(String statement,Object object) —— 插入方法,参数statement是在配置文件中定义的<insert>元素的id,object是插入所需的参数,通常是对象或者Map,返回执行sql语句所影响的行数。

~int update(String statement) —— 更新方法,参数statement是在配置文件中定义的<update> 元素的id,返回执行sql语句所影响的行数。

~ int update(String statement,Object object) —— 更新方法,参数statement是在配置文件中定义的<update>元素的id,object是更新所需的参数,通常是对象或者Map,返回执行sql语句所影响的行数。

~ int delete(String statement) —— 删除方法,参数statement是在配置文件中定义的<delete>元素的id,返回执行sql语句所影响的行数。

~ int delete(String statement,Object object) —— 删除方法,参数statement是在配置文件中定义<delete>元素的id,object是删除所需的参数,通常是对象或者Map,返回执行sql语句影响的行数。

~<T> T selectOne(String statement) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,返回执行sql语句查询结果的泛型对象,通常查询结果只有一条数据时才使用。

~ <T> T selectOne(String statement,Object object) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,返回执行sql语句查询结果的泛型对象,只在查询结果只有一条数据时使用。

~ <E> List<E> selectList(String statement) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,返回sql语句查询结果的泛型对象的集合。

~ <E> List<E> selectList(String statement,Object object) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,返回执行sql语句查询结果的泛型对象的集合。

~ <E> List<E> selectList(String statement,Object object,RowBounds rowBounds) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,RowBounds对象用于分页,它的两个属性:offset指查询的当前页数;limit指当前页显示多少条数据,返回执行sql语句查询结果的泛型对象的集合。

~ <K,V> Map<K,V> selectMap(String statement,String mapKey) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,mapKey是返回数据的其中一个列名,执行sql语句查询结果将会被封装成一个Map集合返回,key就是参数mapKey传入的列名,value是封装的对象。

~ <K,V> Map<K,V> selectMap(String statement,Object object,String mapKey) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,mapKey是返回数据的其中一个列名,执行sql语句查询结果将会被封装成一个Map集合返回,key就是参数mapKey传入的列名,value是封装的对象。

~ <K,V> Map<K,V> selectMap(String statement,Object object,String mapKey,RowBounds rowBounds) —— 查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,RowBounds对象用于分页,mapKey是返回数据的其中一个列名,执行sql语句查询结果将会被封装成一个Map集合返回,key就是参数mapKey传入的列名,value是封装的对象。

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

~ void select(String statement,Object object,RowBounds rowBounds,ResultHandler handler) —— 查询方法,查询方法,参数statement是在配置文件中定义的<select>元素的id,object是查询所需的参数,通常是对象或者Map,ResultHandler对象用来处理查询返回的复杂结果集,RowBounds对象用于分页。

~ void commit() —— 提交事务。

~ void rollback() —— 回滚事务。

~ void close() —— 关闭SqlSession对象。

~Connection getConnection() —— 获得JDBC的数据库连接对象。

~<T> T getMapper(Class<T> type) —— 返回mapper接口的代理对象,该对象关联了SqlSession对象,开发者可以通过该对象直接调用方法操作数据库,参数type是Mapper的接口类型。Mybatis官方手册建议通过Mapper对象访问MyBatis。

三、深入了解MyBatis的配置文件

1.mybatis初始化过程:首先看一段代码

//读取mybatis-config.xml文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//创建Session实例
SqlSession session = sqlSessionFactory.openSession();

其初始化经过的步骤:

(1)、调用SqlSessionFactoryBuilder对象的build(inputStream)方法。

(2)、SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象。

(3)、SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法。

(4)、XMLConfigBuilder对象解析XML配置文件返回Configuration对象。

(5)、SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象。

(6)、SqlSessionFactoryBuilder返回DefaultSessionFactory对象给客户端,供客户端使用。

所以SqlSessionFactory是根据MyBatis的配置文件mybatis-config.xml创建的。

2.Mybatis的配置文件详解

Mybatis包含以下配置元素包含:顶层configuration配置,properties 属性,settings 设置,typeAliases 类型命名,typeHandlers 类型处理器,objectFactory 对象工厂,plugins 插件,environments 环境 ,environment 环境变量,transactionManager 事务管理器,dataSource 数据源,databaseIdProvider 数据库厂商标识,mappers 映射器。

2.1 properties属性

就是将java中属性文件配置,通过properties元素传递到mybatis配置信息中:

例如:java项目中有一个配置文件db.properties

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis
username = root
password = 123456

在mybatis-config.xml配置文件中添加一个属性

<properties resource="db.properties" />

那么mybatis-config.xml配置的动态属性的属性值就可以进行相应的修改

<dataSource type="POOLED">
    <property name="driver" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}"/>
    <property name="password" value="${password}" />
</dataSource>

2.2 settings设置

settings会改变 MyBatis 的运行时行为。其参数详情如下表所示:

settings设置的详细说明
设置参数 描述 有效值 默认值
cacheEnabled 该配置影响所有映射器中配置的缓存的全局开关 true | false true
lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 true | false false
aggressiveLazyLoading 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载 true | false true
multipleResultSetsEnabled 是否允许单一语句返回多结果集(需要兼容驱动) true | false true
useColumnLabel 使用列标签代替列名。不同的驱动在这方面会有不同的表现。 true | false true
useGeneratedKeys 允许JDBC支持自动生成主键,需要驱动兼容。如果设置为true则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作。 true | false false
autoMappingBehavior 指定MyBaits应如果自动映射列到字段或属性。NONE表示取消自动映射;PARTIAL只会自动映射没有定义嵌套结果集映射的结果集。FULL会自动映射任意复杂的结果集(无论是否嵌套) NONE | PARTIAL | FULL PARTIAL
autoMappingUnknownColumnBehavior

NONE:什么都不做

WARNING:输入警告

FAILING:映射失败,抛出SqlSessionException

NONE | WARNING | FAILING NONE
defaultExecutorType 配置默认的执行器。SIMPLE就是普通的执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 SIMPLE | REUSE | BATCH SIMPLE
defaultStatementTimeout 设置超时时间,它决定驱动等待数据库响应的秒数 integer 没有设置
defaultFetchSize 默认返回的结果集的大小 integer 没有设置
safeRowBoundsEnabled 允许在嵌套语句中使用分页(RowBounds) true | false  false
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则(camelcase)映射 true | false false
localCacheScope MyBatis利用本地缓存机制(LocalCache)防止循环引用(circular references)和加速重复嵌套查询。默认值为session,这种情况下会缓存一个会话中执行的所有查询。若设置值为STATEMENT,则本地会话仅用在语句执行上,对相同SqlSession的不同调用将不会共享数据 SESSION | STATEMENT SESSION
jdbcTypeForNull 当没有为参数提供特定的JDBC类型时,为空值指定JDBC类型。某些驱动需要指定列的JDBC类型,多数情况直接用一般类型即可,比如NULL、VARCHAR或OTHER NULL | VARCHAR | OTHER OTHER
lazyLoadTriggerMethods 指定哪个对象的方法触发一次延迟加载 方法名的list集合 equals,clone,hashCode,toString
defaultScriptingLanguage 指定动态SQL生成的默认语言 一个类型别名或完全限定类名

org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver

callSettersOnNulls 指定当结果集中值为null时是否调用映射对象的setter(map对象时为put)方法,这对于有Map.keySet()依赖或null值初始化时是有用的。注意基本类型(int、boolean等)是不能设置成null的 true | false false
logPrefix 指定MyBatis增加到日志名称的前缀 String 没有设置
logImpl 指定MyBatis所有日志的具体实现,未指定时将自动查找

SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMON | S_LOGGING | STDOUT_LOGGING

| NO_LOGGING 

没有设置
proxyFactory 指定Mybatis创建具有延迟加载能力的对象所用到的代理工具 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 or above)

一个完整的setting元素的实例如下:

<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" />
        <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
        <setting name="defaultExecutorType" value="SIMPLE" />
        <setting name="safeRowBoundsEnabled" value="false" />
        <setting name="mapUnderscoreToCamelCase" value="false" />
        <setting name="localCacheScope" value="SESSION" />
        <setting name="jdbcTypeForNull" value="OTHER" />
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

2.3 typeAliases类型命名

可为java类型设置的一个短的名字。该元素可减少类完全限定名的冗余。

<typeAliases>
    <typeAlias type="com.hu.model.User" alias="user"/>
</typeAliases>

在其他配置使用com.hu.model.User可用user代替

 <insert id="saveUser" parameterType="user" useGeneratedKeys="true">
     insert into TB_USER(name,sex,age) values (#{name},#{sex},#{age})
 </insert>

也可以指定一个包名,MyBatis会在包名下面搜索需要的JavaBean

<typeAliases>
    <package name="com.hu.model"/>
</typeAliases>

在每一个包com.hu.model中的javaBean,在没有注解的情况下,会使用Bean的首字母小写的非限定类名来作为它的别名。若有注解,则使用其注解的值。

2.4 typeHandlers 类型处理器

mybatis在预处理语句设置一个参数或从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成Java类型。

MyBatis默认的类型处理器
类型处理器 java类型 JDBC类型
BooleanTypeHandler java.lang.Boolean,boolean 数据库兼容的Boolean
ByteTypeHandler java.lang.Byte, byte 数据库兼容的NUMERIC 或 BYTE
ShortTypeHandler

java.lang.Short,short

数据库兼容的NUMERIC 或SHORT INTEGER
IntegerTypeHandler java.lang.Integer,int 数据库兼容的NUMERIC 或 INTEGER
LongTypeHandler java.lang.Long,long 数据库兼容的NUMERIC 或 LONG INTEGER
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
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类型,存储枚举的名称(而不是索引)

2.5 environments配置环境

environments就是配置mybatis的运行环境,包括事务(transactionManager)和数据源(dataSource)。MyBatis可以配置多种环境,但是每个SqlSessionFactory实例只能选择一个环境,即每个数据库对应一个SqlSessionFactory实例,如果想要连接两个数据库,则需要创建两个SqlSessionFactory实例,以此类推。

environments环境配置实例:

 <!--环境配置,即连接的数据库-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事务管理类型,type="JDBC"指直接使用JDBC的提交和回滚设置-->
            <transactionManager type="JDBC" />
            <!-- dataSource数据源配置,POOLED是JDBC连接对象的数据源连接池的实现。-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                <property name="username" value="root"/>
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>

各种属性说明:

默认的环境id(例:default="mysql")

每个environment 元素定义的环境id(例:id="mysql")

事务管理器的配置(例:type="JDBC")

数据源的配置(例:type="POOLED")

environment的id可以随意命名,但environments的id必须匹配其中一个environment的id

<transactionManager>表示事务管理器配置,在MyBatis中有JDBC和MANAGED两种类型的事务管理器:

        JDBC:这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。

        MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。默认情况下它会关闭连接,然而一些容器并不希望这样,可以将closeConnection属性设置为false来阻止它默认的关闭行为。

transactionManager的MANAGED配置实例:

<transactionManager type="MANAGED">
    <property name="closeConnection" value="false" />
</transactionManager>

注:如果使用的是Spring+MyBatis的架构,则没有必要配置MyBatis的事务管理器,因为会使用Spring框架的自带管理器来覆盖掉MyBatis的配置。

<dataSoucre>表示数据源配置,在MyBatis中有UNPOOLED、POOLED、JNDI三种数据源类型:

        (1)UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。对程序没有性能要求时可使用此配置。

        UNPOOLED包含5种属性配置:

        ·driver —— 这是JDBC驱动的java类的完全限定名。

        ·url —— 这是数据库的JDBC URL 地址。

        ·username —— 登录数据库的用户名。

        ·password —— 登录数据库的密码。

        ·defaultTransactionIsolationLevel —— 默认的连接事务隔离级别。

        (2)POOLED:这种数据源的实现利用了“池”的概念将JDBC连接对象组织起来,避免了创建新的连接实例时所必须的初始化和认证时间。其配置包含上述5种属性外,还有如下属性可配置:

        ·poolMaximumActiveConnections —— 在任意时间可以存在的活动(正在使用)连接数量,默认值为10。

        ·poolMaximumldleConnections —— 任意时间可能存在的空闲连接数。

        ·poolMaximumCheckoutTime —— 在被强制返回之前,池中连接被检出时间,默认值为20000毫米(20s)。

        ·poolTimeToWait —— 这是一个底层设置,如果获取连接花费相当长的时间,它会给连接池打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静地失败),默认值为20000毫秒(20s)。

       ·poolPingQuery —— 发送到数据库的侦测查询,用来检查连接是否处在正常工作秩序中并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。

        ·poolPingEnabled —— 是否启用侦测查询。如开启,必须使用一个可执行的sql语句设置poolPingQuery属性(最好是一个非常快的sql),默认值为false。

        ·poolPingConnectionsNotUsedFor —— 配置poolPingQuery的使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值为0(即所有连接每一时刻都被侦测,仅当poolPingEnabled为true时适用)。

        (3)JNDI:这种数据源的实现是为了能在EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。这中数据源的只有两种配置:

        ·initial_context —— 用来在InitialContext中国寻找上下文(即initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么data_source属性将会直接从InitialContext中寻找。

        ·data_source —— 这是引用数据源实例位置的上下文路径。若提供了initial_context配置则会在其返回的上下文中进行查找,没有提供则直接在InitialContext中查找。

JNDI的配置实例如下:

<dataSource type="JNDI">
    <property name="initial_context" value="java:/comp/env"/>
    <property name="data_source" value="fkjavads"/>
</dataSource>

2.6 mapper 映射器

MyBatis需要自定义sql语句,而mapper则是告诉Mybatis到哪里去找哪些自定义的sql语句的文件,可以使用相对于类路径的资源引用或完全限定资源定位符(包括file:///的URL),以及类名和包名等。

   <!-- mappers告诉了MyBatis去哪里找持久化类的映射文件-->
    <mappers>
      
        <mapper resource="com.hu.mapper.UserMapper.xml"/>
        <!--使用本地文件-->
        <mapper url="file:///D:/UserMapper.xml"/>
        <!--使用接口类-->
        <mapper class="com.hu.mapper.UserMapper" />
        <!--使用包名-->
        <package name="com.hu.mapper"/>
    </mappers>

三、Mapper XML映射文件详解

Mybatis的真正强大之处在于它的映射语句,使用映射器的xml文件进行编写sql语句,相较于使用JDBC来说,可以省略多数代码,使代码更加简洁。

映射文件常用元素如下:

·select —— 映射查询语句。

·insert —— 映射插入语句。

·update —— 映射更新语句。

·delete —— 映射删除语句。

·sql —— 可被其他语句引用的可重用语句块。

·cache —— 给定命名空间的缓存配置。

·cache-ref —— 其他命名空间缓存配置的引用。

·resultMap —— 最复杂最强大的元素,用来描述如何从数据库结果集中加载对象。

3.1 select

select元素用来映射查询语句。实例如下:

<select id="selectUser" parameterType="Integer" resultType="com.hu.model.User">
    select * from TB_USER where id = #{id}
</select>

其中select元素有许多可配置的属性,如下:

<select id="selectUser" parameterType="Integer"
        resultType="hashMap" resultMap="userResultMap"
        flushCache="true" useCache="true"
        timeout="10000" fetchSize="128"
        statementType="PREPARED" resultSetType="FORWARD_ONLY">
</select>

其中各元素的描述如下:

·id —— 在命名空间中唯一的标识符,可以被用来引用这条语句。

·parameterType —— 传入这条语句的参数类的完全限定名或别名。这个属性是可选的,Mybatis可以通过TypeHandler推断出具体传入语句的参数,默认值为unset。

·resultType —— sql语句返回的期望类型的类的完全限定名或别名。如果语句返回的是集合,则是这个集合里包含的类型。返回时只能使用resultType或resutlMap其中的一种,两个不能同时存在。

·resultMap —— 外部resultMap的命名引用,可理解为可自己定义返回的类中的各个字段,一般用于复杂的映射情况。

·flushCache —— 如果设置为true,则只要语句被调用,就会导致本地缓存和二级缓存都被清空,默认值为false。

·useCache —— 如果设置为true,则这要本语句的结果被二级缓存,在select元素当中默认值为true。

·timeout —— 这个设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为unset(依赖驱动)。

·fetchSize —— 尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为unset(依赖驱动)。

·statementType —— 值为STATEMENT、PREPARED、CALLABLE。这会让MyBatis分别使用jdbc中的statement、PreparedStatement、CallableStatement,默认值为PREPARED。

·resultSetType —— 结果集的类型,可选值为FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE,默认值为unset(依赖驱动)。

·resultOrdered —— 这个属性仅针对嵌套结果select语句适用:如果为true,就是假设包含了嵌套结果集或是分组了,当返回一个主结果行的时候,就不会发生对前面结果集引用的情况。这样做的好处就是在获取嵌套的结果集时不至于导致内存不够用。默认值为 false。

·resultSets —— 这个属性仅对多结果集的情况适用,它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的。

3.2 insert、update和delete

其中各元素有许多可配置的属性,如下:

<insert id="insertUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        keyProperty="" keyColumn=""
        useGeneratedKeys="" timeout="20">
</insert>
  
      
<update id="updateUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        timeout="20">
</update>

<delete id="deleteUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        timeout="20">            
</delete>

其中各元素属性大多数和select一致,特有属性描述如下:

·useGeneratedKeys —— (仅对insert和update有用)这会让MyBatis使用JDBC的getGeneratedKeys方法来获取由数据库内部生成的主键,默认值为false。

·keyProperty —— (仅对insert和update有用)唯一标示属性,MyBatis会通过getGeneratedKeys的返回值或者通过insert语句的selectKey子元素设置它的键值,默认为unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

·keyColumn —— (仅对insert和update有用)通过生成的键值设置表中的列名,这个设置仅对某些数据库(像PostgreSQL)是必须的,当主键列不是表中的第一列时需要设置。如果希望得到多个生成的列,也可以示逗号分隔的属性名称列表。

对于insert语句来说,在插入数据成功后需要返回其表中的主键值,根据数据库的主键生成策略不同,配置也有多种;如果数据库支持自动生成主键的字段(如Mysql和SQL Server),那么可以设置useGeneratedKeys=“true”,然后再把keyProperty设置到目标属性上就可以了。语句实例如下:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into TB_USER (username,password,address) values 
    (#{username},#{password},#{address})
</insert>

对于不支持自动生成主键的数据库(如Oracle)或可能不支持自动生成主键的jdbc驱动来说,Mybatis有另外一种方法生成主键。

<insert id="insertUser">
    <selectKey keyProperty="id" resultType="Integer" order="BEFORE">
        select SQQUENCE_TB_USER.nextval as id from dual
    </selectKey>
    insert into TB_USER (id,username,password,address)
    values (#{id},#{username},#{password},#{address})
</insert>

上述代码selectKey元素将会首先运行,查询到SEQUENCE序列,TB_USER的id会被设置,然后在执行insert语句;其中selectKey元素描述如下:

<selectKey keyProperty="id" 
           resultType="Integer" 
           order="BEFORE" 
           statementType="PREPARED">
            

属性详细解析:

·keyProperty —— selectKey语句结果被设置的目标属性(一般会设置到id属性上)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

·keyColumn —— 匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

·resultType —— 结果的类型Mybatis允许任何简单类型用作主键的类型,包括字符串,如果希望作用于多个生成的列,则可以使用一个包含期望属性的Object或一个Map。

·order —— 可设置为BEFORE或AFTER,如果设置为BEFORE,就是首先生成主键,然后将keyProperty的值插入到语句中;如果设置为AFTER,那就先执行插入语句,然后在执行selectKey元素。

·statementType —— 值为STATEMENT、PREPARED、CALLABLE。这会让MyBatis分别使用jdbc中的statement、PreparedStatement、CallableStatement,默认值为PREPARED。

3.3 sql

sql元素可以被用来定义可重用的sql代码,可以包含在其他语句中。它可以被静态地(在加载参数时)参数化。代码实例:

<sql id="userColumns"> id,username,password</sql>

在别语句中就可调用这个sql代码,实例如下:

<select id="selectUsers" resultType="map">
    select 
        <include refid="userColumns"></include>
    from TB_USER 
</select>

3.4 参数(Parameters)

parameterType传入sql语句的参数类型,参数类型可以是原生的类型或简单数据类型,也可传入一个对象,例如:

<insert id="insertUser" parameterType="User">
    insert into user (id,username,password)
     values (#{id},#{username},#{password})
</insert>

如果是Userr实体被传入sql语句中,#{id}则会查找对象User的id属性。

3.5 ResultMap(ResultType)

resultMap(ResultType)的作用是告诉MyBatis将从结果集中取出的数据转换成开发着所需要的对象。例如:

<select id="selectUser" resultType="map">
    select * from tb_user
</select>

上诉语句就是查询tb_user表中的所有数据。resultTyep=“map”表示返回的数据是一个Map集合(表的列名作为key,列值作为value)。虽然数据被封装成了Map集合,但是Map集合并不能很好的描述一个领域模型。所以最好还是使用javaBeans或pojo来作为领域模型描述数据。

如果查询的结果是由两张表关联的字段组成,则就不能用resultType,这时就可以使用resultMap,或者数据库表的字段和实例不对应,这时也可以使用resutlMap。例如:

创建一个数据库表:

create table user2(
    user_id int primary key auto_increment,
    user_name archer(8),
    user_sex archer(8),
    user_age int(4)
);

java对应的实体:

public class User {

   /** 标识 */
    private Integer id;

    /** 姓名 */
    private String name;

    /** 性别 */
    private String sex;

    /** 年龄 */
    private Integer age;

    //省略get/set方法
}

这个时候就可以使用resultMap:

<resultMap id="userResultMap" type="com.hu.model.User">
    <id property="id" column="user_id" />
    <result property="name" column="user_name"/>
    <result property="sex" column="user_sex" />
    <result property="age" column="user_age" />
</resultMap>

<select id="selectUser2" resultMap="userResultMap">
    select * from user2
 </select>

上述resultMap元素属性解析如下:

·id —— resultMap的唯一标识符。

·type —— resultMap实际返回的类型。

resultMap的两个子元素:

·id —— 表示数据库表的主键,其中,column属性表示数据库表的列名,property表示数据库列映射到返回类型的属性。

·result —— 表示数据库表普通列,其中,column属性表示数据库表的列名,property表示数据库列映射到返回类型的属性。

对于多表的关联映射也需要使用ResultMap来实现,例如:先创建两个关联的表

create table class{
    id int primary key auto_increment,
    code varchar(8)
};


create table student{
    id int primary key auto_increment,
    name varchar(8),
    sex char(3),
    age int(5),
    clazz_id int,
    foreign key (class_id) references class(id)

};

在java分别对应的实体为:

public class Clazz {

    private Integer id;

    private String code;

    //省略get/set方法
}


public class Student {

    private Integer id;

    private String name;

    private String sex;

    private String age;

    private Clazz clazz;

   //省略get/set方法

}

mapper映射文件的写法为:

 <resultMap id="studentClazz" type="com.hu.model.Student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <!--关联映射-->
        <association property="clazz" column="clazz_id" javaType="com.hu.model.Clazz" select="selectClazzId"/>
    </resultMap>
    
    <!--根据班级id查询班级-->
    <select id="selectClazzId" resultType="com.hu.model.Clazz">
        select * from  clazz where  id = #{id}
    </select>
    <!--查询所有学生信息-->
    <select id="selectStudent" resultMap="studentClazz">
        select * from student
    </select>

上诉<association>元素解释如下:

·column —— 表示数据库表的列名。

·property —— 表示返回类型student的属性名clazz

·javaType —— 表示该属性对应的类型名称。

·select —— 表示执行一条查询语句,将查询到的数据封装property所代表的类型对象当中。上面的selectClazzId就是一条sql语句。

如果想查询一个班级所有的学生信息的话,首先在clazz.java类中增加一个students字段,其类型为List集合。此时映射文件如下所示:

<resultMap id="clazzStudent" type="com.hu.model.Clazz">
        <id property="id" column="id" />
        <result property="code" column="code" />
        <!--班级的学生属性,因为一个班级有多个学生,所以该属性是一个集合-->
        <collection property="students" javaType="ArrayList" column="id" ofType="com.hu.model.Student"
                    select="selectStudentId" />
        
    </resultMap>
    <!--根据班级id查询学生-->
    <select id="selectStudentId" resultType="com.hu.model.Student">
        select * from student where clazz_id = #{id}
    </select>
    <!--查询所有班级信息-->
    <select id="selectClazz" resultMap="clazzStudent">
        select * from clazz
    </select>

其中元素<collection>详解如下:

·property —— 表示返回类型Clazz的属性名students。

·javaType —— 表示该属性对应的类型名称。

·ofType —— 表示集合当中的类型。

·column —— 表示使用id作为参数进行之后的select语句查询。

·select —— 表示执行一条查询语句,将查询到的数据封装property所代表的类型对象当中。上面的selectStudentId就是一条sql语句。

猜你喜欢

转载自blog.csdn.net/huxiaodong1994/article/details/81951838