一、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 的运行时行为。其参数详情如下表所示:
设置参数 | 描述 | 有效值 | 默认值 |
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类型。
类型处理器 | 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语句。