1.MyBatis一般使用步骤
1.1获取Configuration实例或编写配置文件
//获取Configuration实例的样例
TransactionFactory transactionFactory = new JdbcTransactionFactory();//定义事务工厂
Environment environment =
new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
1.2生成SqlSessionFactory实例
一个数据库对应一个SqlSessionFactory
//通过Configuration实例生成SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
//通过xml配置文件方式生成SqlSessionFactory
String resource = "org/mybatis/example/Configuration.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlSessionFactory= new SqlSessionFactoryBuilder().build(reader);
1.3生成SqlSession实例
//样例
SqlSession session = sqlSessionFactory.openSession();
1.4执行sql各种操作
//样例
try {
Blog blog = (Blog) session.selectOne(
"org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
session.close();
}
2.MyBatis的配置文件解析
2.0 mybatis-config.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>
<!-- 参数设置 -->
<settings>
<!-- 这个配置使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载 -->
<setting name="aggressiveLazyLoading" value="true" />
<!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动) -->
<setting name="multipleResultSetsEnabled" value="true" />
<!-- 使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方法来决定所使用的驱动 -->
<setting name="useColumnLabel" value="true" />
<!-- 允许JDBC支持生成的键。需要适合的驱动。如果设置为true则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如Derby) -->
<setting name="useGeneratedKeys" value="true" />
<!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单,没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) -->
<setting name="autoMappingBehavior" value="PARTIAL" />
<!--当检测出未知列(或未知属性)时,如何处理,默认情况下没有任何提示,这在测试的时候很不方便,不容易找到错误。
NONE : 不做任何处理 (默认值)
WARNING : 警告日志形式的详细信息
FAILING : 映射失败,抛出异常和详细信息
-->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 -->
<setting name="defaultStatementTimeout" value="25000" />
<!--设置查询返回值数量,可以被查询数值覆盖 -->
<setting name="defaultFetchSize" value="100"/>
<!-- 允许在嵌套语句中使用分页-->
<setting name="safeRowBoundsEnabled" value="false"/>
<!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!--MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。-->
<setting name="localCacheScope" value="SESSION"/>
<!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR
OTHER。-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!-- 指定哪个对象的方法触发一次延迟加载。-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
<!-- 别名定义 -->
<typeAliases>
<typeAlias alias="pageAccessURL" type="com.lgm.mybatis.model.PageAccessURL" />
</typeAliases>
<!--自定义类型处理器 -->
<typeHandlers>
<!-- <typeHandler handler="com.xhm.util.BooleanTypeHandlder" /> -->
<!--扫描整个包下的自定义类型处理器-->
<package name="com.xhm.util"/>
</typeHandlers>
<!--plugins插件之 分页拦截器 -->
<plugins>
<plugin interceptor="com.xhm.util.PageInterceptor"></plugin>
</plugins>
<!--配置environment环境-->
<environments default="development">
<!-- 环境配置1,每个SqlSessionFactory对应一个环境 -->
<environment id="development1">
<!-- 事务配置 type= JDBC、MANAGED 1.JDBC:这个配置直接简单使用了JDBC的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。
2.MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如Spring或JEE应用服务器的 上下文)。 默认情况下它会关闭连接。然而一些容器并不希望这样,因此如果你需要从连接中停止它,将closeConnection属性设置为false -->
<transactionManager type="JDBC" />
<!-- <transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager> -->
<!-- 数据源类型:type = UNPOOLED、POOLED、JNDI1.UNPOOLED:这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢,这是对简单应用程序的一个很好的选择,因为它不需要及时的可用连接。
不同的数据库对这个的表现也是不一样的,所以对某些数据库来说配置数据源并不重要,这个配置也是闲置的 2.POOLED:这是JDBC连接对象的数据源连接池的实现,用来避免创建新的连接实例时必要的初始连接和认证时间。
这是一种当前Web应用程序用来快速响应请求很流行的方法。3.JNDI:这个数据源的实现是为了使用如Spring或应用服务器这类的容器,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用 -->
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/xhm" />
<property name="username" value="root" />
<property name="password" value="root" />
<!-- 默认连接事务隔离级别 <property name="defaultTransactionIsolationLevel" value=""
/> -->
</dataSource>
</environment>
<!-- 环境配置2 -->
<environment id="development2">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/xhm" />
<property name="username" value="root" />
<property name="password" value="root" />
<!-- 在任意时间存在的活动(也就是正在使用)连接的数量 -->
<property name="poolMaximumActiveConnections" value="10" />
<!-- 任意时间存在的空闲连接数 -->
<property name="poolMaximumIdleConnections" value="5" />
<!-- 在被强制返回之前,池中连接被检查的时间 -->
<property name="poolMaximumCheckoutTime" value="20000" />
<!-- 这是给连接池一个打印日志状态机会的低层次设置,还有重新尝试获得连接,这些情况下往往需要很长时间(为了避免连接池没有配置时静默失败) -->
<property name="poolTimeToWait" value="20000" />
<!-- 发送到数据的侦测查询,用来验证连接是否正常工作,并且准备接受请求。 -->
<property name="poolPingQuery" value="NO PING QUERY SET" />
<!-- 这是开启或禁用侦测查询。如果开启,你必须用一个合法的SQL语句(最好是很快速的)设置poolPingQuery属性 -->
<property name="poolPingEnabled" value="false" />
<!-- 这是用来配置poolPingQuery多次时间被用一次。这可以被设置匹配标准的数据库连接超时时间,来避免不必要的侦测 -->
<property name="poolPingConnectionsNotUsedFor" value="0" />
</dataSource>
</environment>
<!-- 环境配置3 -->
<environment id="development3">
<transactionManager type="JDBC" />
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jndi/mybatis" />
<property name="env.encoding" value="UTF8" />
<!-- <property name="initial_context" value=""/> <property name="env.encoding"
value="UTF8"/> -->
</dataSource>
</environment>
</environments>
<!-- 映射文件,mapper的配置文件 -->
<mappers>
<!--直接映射到相应的mapper文件-->
<mapper resource="com/xhm/mapper/UserMapper.xml"/>
<!--扫描包路径下所有xxMapper.xml文件-->
<package name="com.xhm.mapper"/>
</mappers>
</configuration>
2.1配置文件的基本结构
configuration —— 根元素
properties —— 定义配置外在化
settings —— 一些全局性的配置
typeAliases —— 为一些类定义别名
typeHandlers —— 定义类型处理,也就是定义java类型与数据库中的数据类型之间的转换关系
objectFactory
plugins —— Mybatis的插件,插件可以修改Mybatis内部的运行规则
environments —— 配置Mybatis的环境
environment
transactionManager —— 事务管理器
dataSource —— 数据源
databaseIdProvider
mappers —— 指定映射文件或映射类
2.2 properties元素——定义配置外在化
<!--样例-->
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
配置外在化的属性还可以通过SqlSessionFactoryBuilder.build()方法提供,如:
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);
配置外在化的优先级是 build方法->resource属性指定的文件->property元素
2.3 settings元素——Mybatis的一些全局配置属性
设置参数 描述 有效值 默认值
cacheEnabled 这个配置使全局的映射器启用或禁用 缓存。 true | false true
lazyLoadingEnabled 全局启用或禁用延迟加载。当禁用时, 所有关联对象都会即时加载。 true | false true
aggressiveLazyLoading 当启用时, 有延迟加载属性的对象在被 调用时将会完全加载任意属性。否则, 每种属性将会按需要加载。 true | false true
multipleResultSetsEnabled 允许或不允许多种结果集从一个单独 的语句中返回(需要适合的驱动) true | false true
useColumnLabel 使用列标签代替列名。 不同的驱动在这 方便表现不同。 参考驱动文档或充分测 试两种方法来决定所使用的驱动。 true | false true
useGeneratedKeys 允许 JDBC 支持生成的键。 需要适合的 驱动。 如果设置为 true 则这个设置强制 生成的键被使用, 尽管一些驱动拒绝兼 容但仍然有效(比如 Derby) true | false False
autoMappingBehavior 指定 MyBatis 如何自动映射列到字段/ 属性。PARTIAL 只会自动映射简单, 没有嵌套的结果。FULL 会自动映射任 意复杂的结果(嵌套的或其他情况) 。 NONE, PARTIAL, FULL PARTIAL
defaultExecutorType 配置默认的执行器。SIMPLE 执行器没 有什么特别之处。REUSE 执行器重用 预处理语句。BATCH 执行器重用语句 和批量更新 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设置超时时间, 它决定驱动等待一个数 据库响应的时间。 Any positive integer Not Set (null)
safeRowBoundsEnabled Allows using RowBounds on nested statements. true | false False
mapUnderscoreToCamelCase Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. true | false False
localCacheScope MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be used just for statement execution, no data will be shared between two different calls to the same SqlSession. SESSION | STATEMENT SESSION
jdbcTypeForNull Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods Specifies which Object‘s methods trigger a lazy load A method name list separated by commas equals,clone,hashCode,toString
2.4 typeAliases元素
定义类别名,简化xml文件的配置,如:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
Mybatis还内置了一些类型别名:
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator
2.5 typeHandlers元素
每当MyBatis 设置参数到PreparedStatement 或者从ResultSet 结果集中取得值时,就会使用TypeHandler 来处理数据库类型与java 类型之间转换。
2.5.1 自定义typeHandlers
实现TypeHandler接口
在配置文件中声明自定义的TypeHandler
2.5.2 Mybatis内置的TypeHandler
类型处理器 Java 类型 JDBC 类型
BooleanTypeHandler java.lang.Boolean, boolean 任何兼容的布尔值
ByteTypeHandler java.lang.Byte, byte 任何兼容的数字或字节类型
ShortTypeHandler java.lang.Short, short 任何兼容的数字或短整型
IntegerTypeHandler java.lang.Integer, int 任何兼容的数字和整型
LongTypeHandler java.lang.Long, long 任何兼容的数字或长整型
FloatTypeHandler java.lang.Float, float 任何兼容的数字或单精度浮点型
DoubleTypeHandler java.lang.Double, double 任何兼容的数字或双精度浮点型
BigDecimalTypeHandler java.math.BigDecimal 任何兼容的数字或十进制小数类型
StringTypeHandler java.lang.String CHAR 和 VARCHAR 类型
ClobTypeHandler java.lang.String CLOB 和 LONGVARCHAR 类型
NStringTypeHandler java.lang.String NVARCHAR 和 NCHAR 类型
NClobTypeHandler java.lang.String NCLOB 类型
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 其他或未指定类型
EnumTypeHandler Enumeration Type VARCHAR-任何兼容的字符串类型, 作为代码存储(而不是索引)
EnumOrdinalTypeHandler Enumeration Type Any compatible NUMERIC or DOUBLE, as the position is stored (not the code itself).
2.6 objectFactory元素——用于指定结果集对象的实例是如何创建的。
下面演示了如何自定义ObjectFactory
1.继承DefaultObjectFactory
2.在配置文件中配置自定义的ObjectFactory
2.7 plugins元素
MyBatis 允许您在映射语句执行的某些点拦截方法调用。默认情况下,MyBatis 允许插件(plugins)拦截下面的方法:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
下面是自定义plugin示例:
实现Interceptor接口,并用注解声明要拦截的方法
// ExamplePlugin.java
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
在配置文件中声明插件
2.8 Environments元素
可以配置多个运行环境,但是每个SqlSessionFactory 实例只能选择一个运行环境。
2.8.1 Environments配置示例:
2.8.2 transactionManager事务管理器
MyBatis 有两种事务管理类型(即type=”[JDBC|MANAGED]”):
JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让 容器来管理事务的整个生命周期(比如 Spring 或 JEE 应用服务器的上下文) 默认 情况下它会关闭连接。 然而一些容器并不希望这样, 因此如果你需要从连接中停止 它,将 closeConnection 属性设置为 false。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
自定义事务管理器:
实现TranscactionFactory,它的接口定义如下:
实现TransactionFactory,它的接口定义如下:
public interface Transaction {
Connection getConnection();
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
2.8.3 dataSource数据源
dataSource 元素使用标准的JDBC 数据源接口来配置JDBC 连接对象源。
MyBatis 内置了三种数据源类型:
UNPOOLED – 这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢, 这是对简单应用程序的一个很好的选择, 因为它不需要及时的可用连接。 不同的数据库对这 个的表现也是不一样的, 所以对某些数据库来说配置数据源并不重要, 这个配置也是闲置的。 UNPOOLED 类型的数据源仅仅用来配置以下 5 种属性:
driver – 这是 JDBC 驱动的 Java 类的完全限定名(如果你的驱动包含,它也不是 数据源类)。
url – 这是数据库的 JDBC URL 地址。
username – 登录数据库的用户名。
password – 登录数据库的密码。
defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
作为可选项,你可以传递数据库驱动的属性。要这样做,属性的前缀是以“driver.”开 头的,例如:
driver.encoding=UTF8
这 样 就 会 传 递 以 值 “ UTF8 ” 来 传 递 属 性 “ encoding ”, 它 是 通 过 DriverManager.getConnection(url,driverProperties)方法传递给数据库驱动。
POOLED – 这是 JDBC 连接对象的数据源连接池的实现,用来避免创建新的连接实例 时必要的初始连接和认证时间。这是一种当前 Web 应用程序用来快速响应请求很流行的方 法。
除了上述(UNPOOLED)的属性之外,还有很多属性可以用来配置 POOLED 数据源:
poolMaximumActiveConnections – 在任意时间存在的活动(也就是正在使用)连 接的数量。默认值:10
poolMaximumIdleConnections – 任意时间存在的空闲连接数。
poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检查的时间。默认 值:20000 毫秒(也就是 20 秒)
poolTimeToWait – 这是给连接池一个打印日志状态机会的低层次设置,还有重新 尝试获得连接, 这些情况下往往需要很长时间 为了避免连接池没有配置时静默失 败)。默认值:20000 毫秒(也就是 20 秒)
poolPingQuery – 发送到数据的侦测查询,用来验证连接是否正常工作,并且准备 接受请求。默认是“NO PING QUERY SET” ,这会引起许多数据库驱动连接由一 个错误信息而导致失败。
poolPingEnabled – 这是开启或禁用侦测查询。如果开启,你必须用一个合法的 SQL 语句(最好是很快速的)设置 poolPingQuery 属性。默认值:false。
poolPingConnectionsNotUsedFor – 这是用来配置 poolPingQuery 多次时间被用一次。 这可以被设置匹配标准的数据库连接超时时间, 来避免不必要的侦测。 默认值: 0(也就是所有连接每一时刻都被侦测-但仅仅当 poolPingEnabled 为 true 时适用)。
JNDI – 这个数据源的实现是为了使用如 Spring 或应用服务器这类的容器, 容器可以集 中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这个数据源配置只需要两个属 性:
initial_context – 这 个 属 性 用 来 从 初 始 上 下 文 中 寻 找 环 境 ( 也 就 是 initialContext.lookup(initial——context) 。这是个可选属性,如果被忽略,那么 data_source 属性将会直接以 initialContext 为背景再次寻找。
data_source – 这是引用数据源实例位置的上下文的路径。它会以由 initial_context 查询返回的环境为背景来查找,如果 initial_context 没有返回结果时,直接以初始 上下文为环境来查找。
和其他数据源配置相似, 它也可以通过名为 “env.” 的前缀直接向初始上下文发送属性。 比如:
env.encoding=UTF8
在初始化之后,这就会以值“UTF8”向初始上下文的构造方法传递名为“encoding” 的属性。
2.9 mappers元素
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。 但是, 首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在这方面没有提供一个很好 的方法, 所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的 资源引用,或者字符表示,或 url 引用的完全限定名(包括 file:///URLs) 。例如:
<!-- Using classpath relative resources -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
3.SQL映射配置文件的结构概览
cache – 配置给定命名空间的缓存。
cache-ref – 从其他命名空间引用缓存配置。
resultMap – 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载你的对象。
parameterMap – 已经被废弃了!老式风格的参数映射。内联参数是首选,这个元 素可能在将来被移除。这里不会记录。
sql – 可以重用的 SQL 块,也可以被其他语句引用。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句
4.select元素
简单示例:
<select id=”selectPerson” parameterType=”int” resultType=”hashmap”>
SELECT * FROM PERSON WHERE ID = #{id}
</select>
这段sql语句的意思是传入一个int类型的参数给select语句,返回的结果集保存在hashmap中,hashmap的key为字段名。
这里的#{id}就是使用PrepareStatement的方式传入参数,即像这样:
String selectPerson = “SELECT * FROM PERSON WHERE ID=?”;
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
select元素支持的属性:
Select Attributes
属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数类的完全限定名或别名。
parameterMap 这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数 映射和 parameterType 属性。
resultType 从这条语句中返回的期望类型的类的完全限定名或别名。注意集 合情形,那应该是集合可以包含的类型,而不能是集合本身。使 用 resultType 或 resultMap,但不能同时使用。
resultMap 命名引用外部的 resultMap。 返回 map 是 MyBatis 最具力量的特性, 对其有一个很好的理解的话, 许多复杂映射的情形就能被解决了。 使用 resultMap 或 resultType,但不能同时使用。
flushCache 将其设置为 true,不论语句什么时候被带哦用,都会导致缓存被 清空。默认值:false。
useCache 将其设置为 true, 将会导致本条语句的结果被缓存。 默认值: true。
timeout 这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的 最大等待值。默认不设置(驱动自行处理)
fetchSize 这是暗示驱动程序每次批量返回的结果行数。默认不设置(驱动 自行处理)。
statementType STA TEMENT,PREPARED 或 CALLABLE 的一种。 这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。 默认值:PREPARED。
resultSetType FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE 中的一种。默认是不设置(驱动自行处理)。
databaseId In case there is a configured databaseIdProvider, MyBatis will load all statements with no databaseId attribute or with a databaseId that matches the current one. If case the same statement if found with and without the databaseId the latter will be discarded.
5.Insert、update、delete 元素
数据修改语句insert、update 和delete 的配置使用都非常相似,只是insert元素多了两个属性配置(useGeneratedKey,keyProperty,keyColumn)。
下面是insert元素的示例(update,delete元素也差不多):
<!--自动生成主键-->
<insert id="insertAuthor" parameterType="domain.blog.Author"
useGeneratedKeys=”true” keyProperty=”id”>
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
<!--通过一个查询来生成主键-->
<insert id="insertAuthor" parameterType="domain.blog.Author">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio},
#{favouriteSection,jdbcType=VARCHAR}
)
</insert>
Insert, Update and Delete Attributes
属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数类的完全限定名或别名。
parameterMap 这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数 映射和 parameterType 属性。
flushCache 将其设置为 true,不论语句什么时候被带哦用,都会导致缓存被清 空。默认值:false。
timeout 这个设置驱动程序等待数据库返回请求结果, 并抛出异常时间的最 大等待值。默认不设置(驱动自行处理)。
statementType STA TEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。 默认值:PREPARED。
useGeneratedKeys ( 仅 对 insert 有 用 ) 这 会 告 诉 MyBatis 使 用 JDBC 的 getGeneratedKeys 方法来取出由数据(比如:像 MySQL 和 SQL Server 这样的数据库管理系统的自动递增字段)内部生成的主键。 默认值:false。
keyProperty (仅对 insert 有用) 标记一个属性, MyBatis 会通过 getGeneratedKeys 或者通过 insert 语句的 selectKey 子元素设置它的值。 默认: 不设置。
keyColumn (仅对 insert 有用) 标记一个属性, MyBatis 会通过 getGeneratedKeys 或者通过 insert 语句的 selectKey 子元素设置它的值。 默认: 不设置。
6.parameter(参数)
我们可以向#{id},#{name}这样形式的语句转入参数,但我们还可以更加具体地声明参数的java类型,jdbc类型,以及使用哪个TypeHandler,对于jdbc类型是NUMERIC的参数,还可以指定他的小数位数,如:
#{age,javaType=int,jdbcType=NUMERIC,numbericScale=2,typeHandler=MyTypeHandler}
除了这些外,还可以声明参数是IN,OUT或INOUT模式
#{age,javaType=int,jdbcType=NUMERIC,numbericScale=2,typeHandler=MyTypeHandler,mode=INOUT}
还可以使用${str}形式,把str参数的直接字符串值替换到${str}符号中,这种方式尽量少用,因为这会造成SQL注入的问题。
7.sql元素
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。比如:
<sql id="userColumns"> id,username,password </sql>
<select id="selectUsers" parameterType="int" resultType="hashmap">
select <include refid="userColumns"/>
from some_table
where id = #{id}
</select>
8.resultMap元素
resultMap的概览视图:
constructor - 类在实例化时,用来注入结果到构造方法中
idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能
arg - 注入到构造方法的一个普通结果
id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能
result – 注入到字段或 JavaBean 属性的普通结果
association – 一个复杂的类型关联;许多结果将包成这种类型
嵌入结果映射 – 结果映射自身的关联,或者参考一个
collection – 复杂类型的集
嵌入结果映射 – 结果映射自身的集,或者参考一个
discriminator – 使用结果值来决定使用哪个结果映射
case – 基于某些值的结果映射
嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。
8.1 id、result及constructor
这三个元素使用起来都非常相似的,它们只能用于简单类型数据。
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
这些元素支持的属性:
属性 描述
property 映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同 的 JavaBeans 的属性,那么就会使用。否则 MyBatis 将会寻找给定名称 property 的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你 可以这样映射一些东西: “username” ,或者映射到一些复杂的东西: “address.street.number” 。
column 从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会 传递给 resultSet.getString(columnName)方法参数中相同的字符串。
javaType 一个 Java 类的完全限定名,或一个类型别名(参加上面内建类型别名 的列表) 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。 然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的行为。
jdbcType 在这个表格之后的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅 仅需要对插入,更新和删除操作可能为空的列进行处理。这是 JDBC jdbcType 的需要,而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定 这个类型-但仅仅对可能为空的值。
typeHandler 我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默 认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理 器的实现,或者是类型别名。
这些元素的映射支持的JDBC类型有:
BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED
TINYINT REAL VARCHAR BINARY BLOG NVARCHAR
SMALLINT DOUBLE LONGVARCHAR VARBINARY CLOB >NCHAR
INTEGER NUMERIC DATE LONGVARBINARY BOOLEAN NCLOB
BIGINT DECIMAL TIME NULL CURSOR ARRAY
8.2 association关联查询
association关联查询用于处理一对一关系,它可以使用两种方式查询这个关联对象:嵌套查询方式和嵌套结果方式。
8.2.1 嵌套查询方式
示例:
<resultMap id="blogResult" type="Blog">
<association property="author" column="blog_author_id" javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectBlog" parameterType="int" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id="selectAuthor" parameterType="int" resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
Notice:嵌套查询的属性column,表示该关联对象是通过哪个字段查询得到的,该字段的值会被当作参数传递到嵌套查询selectAuthor中。
Notice:嵌套查询方式可以很容易地实现递归查询,而嵌套结果方式是不能实现递归查询的。
8.2.2嵌套结果方式
示例:
<select id="selectBlog" parameterType="int" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio
from Blog B left outer join Author A on B.author_id = A.id
where B.id = #{id}
</select>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
Notice:嵌套结果方式一般对应的是一个多表连接查询,把查询出来的结果集映射到关联对象上。
在多表连接查询中,一般都会重用resultMap,但连接查询的结果集的列名要求是不一样的,association元素提供了一个columnPrefix属性来解决这个问题。如一篇文章有两个作者共同完成,一个主编,一个副编。
<select id="selectBlog" parameterType="int" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
CA.id as co_author_id,
CA.username as co_author_username,
CA.password as co_author_password,
CA.email as co_author_email,
CA.bio as co_author_bio
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Author CA on B.co_author_id = CA.id
where B.id = #{id}
</select>
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author"
resultMap="authorResult" />
<association property="coAuthor"
resultMap="authorResult"
columnPrefix="co_" />
</resultMap>
8.3 collection集合映射
集合映射是用于解决一对多的关系模型映射问题。它与关联映射非常相似,这里主要说明集合映射的一些不同点。
Notice:collection的column属性表示查询该集合所需要的列或字段,它会被作为参数传递到嵌套查询中。
这里展示一个例子,如何使用嵌套查询来实现递归查询:
8.3.1典型的树型表结构
上图是Category表的结构图,其中parent_id是外键,它引用同一个表的id字段。这其实就是经典的在同一个表中实现树型结构。
8.3.2 Category表的数据
8.3.3 配置mybatis的映射文件,实现递归查询
<resultMap id="categoryResultMap" type="Category">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<association property="parent" column="parent_id" select="selectCategoryById"></association><!-- 递归查询,只能用select方式 -->
<collection property="children" column="id" ofType="Category" javaType="java.util.ArrayList"
select="selectCategoryChildren"></collection><!-- 递归查询,只能用select方式 -->
</resultMap>
<select id="selectAllCategory" resultMap="categoryResultMap">
select * from category;
</select>
<select id="selectCategoryById" resultMap="categoryResultMap"
parameterType="int">
select * from category where id=#{parent_id}
</select>
<select id="selectCategoryChildren" resultMap="categoryResultMap"
parameterType="int">
select * from category where parent_id=#{id}
</select>
9.动态SQL
MyBatis中用于实现动态SQL的元素主要有:
if
if就是简单的条件判断,利用if语句我们可以实现某些简单的条件选择。
<select id="findAllInfosCount" resultType="int">
select count(*) from student where 1=1
<if test="name != null and name != ‘‘"> and NAME like CONCAT(‘%‘,‘${name}‘,‘%‘)</if>
<if test="gender != null and gender != ‘‘"> and GENDER = #{gender}</if>
<if test="course != null and course != ‘‘"> and COURSE = #{course}</if>
<if test="examdate != null and examdate != ‘‘"> and EXAMDATE between #{examdate}</if>
</select>
<select id="findAllInfos" parameterType="com.cib.yypt.sample.vo.StudentVO" resultMap="studentMap">
select STUDENTZJ,STUDENTID,NAME,GENDER,COURSE,SCORE,EXAMDATE from student where 1=1
<if test="name != null and name != ‘‘"> and NAME like CONCAT(‘%‘,‘${name}‘,‘%‘)</if>
<if test="gender != null and gender != ‘‘"> and GENDER = #{gender}</if>
<if test="course != null and course != ‘‘"> and COURSE = #{course}</if>
<if test="examdate != null and examdate != ‘‘"> and EXAMDATE between #{examdate}</if>
</select>
choose(when,otherwise)
choose元素的作用就相当于JAVA中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。
<select id="dynamicChooseTest" parameterType="Blog" resultType="Blog">
select * from t_blog where 1 = 1
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="content != null">
and content = #{content}
</when>
<otherwise>
and owner = "owner1"
</otherwise>
</choose>
</select>
trim
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和 suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能,示例代码如下:
<select id="dynamicTrimTest" parameterType="Blog" resultType="Blog">
select * from t_blog
<trim prefix="where" prefixOverrides="and |or">
<if test="title != null">
title = #{title}
</if>
<if test="content != null">
and content = #{content}
</if>
<if test="owner != null">
or owner = #{owner}
</if>
</trim>
</select>
where
where语句的作用主要是简化SQL语句中where中的条件判断的,where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子 的,MyBatis会智能的帮你处理,如果所有的条件都不满足那么MyBatis就会查出所有的记录,如果输出后是and 开头的,MyBatis会把第一个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在where元素中你不需要考虑空格的问 题,MyBatis会 智能的帮你加上。像上述例子中,如果title=null, 而content != null,那么输出的整个语句会是select * from t_blog where content = #{content},而不是select * from t_blog where and content = #{content},因为MyBatis会智能的把首个and 或 or 给忽略。
<select id="dynamicWhereTest" parameterType="Blog" resultType="Blog">
select * from t_blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="content != null">
and content = #{content}
</if>
<if test="owner != null">
and owner = #{owner}
</if>
</where>
</select>
set
set元素主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的,主要是在包含的语句前输出一个 set,然后如果包含的语句是以逗号结束的话将会把该逗号忽略,如果set包含的内容为空的话则会出错。有了set元素我们就可以动态的更新那些修改了的 字段。
<update id="dynamicSetTest" parameterType="Blog">
update t_blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="content != null">
content = #{content},
</if>
<if test="owner != null">
owner = #{owner}
</if>
</set>
where id = #{id}
</update>
foreach
foreach的主要用在构建in条件中, 它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有 item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔 符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
单参数List的类型
<select id="dynamicForeachTest" resultType="Blog">
select * from t_blog where id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
单参数array数组的类型
<select id="dynamicForeach2Test" resultType="Blog">
select * from t_blog where id in
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
自己把参数封装成Map的类型
<select id="dynamicForeach3Test" resultType="Blog">
select * from t_blog where title like "%"#{title}"%" and id in
<foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>