作者:longgangbai

以前用过ibatis2,但是听说ibatis3有较大的性能提升,而且设计也更合理,他不兼容ibatis2.尽管ibatis3还是beta10的状态,但还是打算直接使用ibatis3.0, 
ibatis3.0应该更简单高效.最近还自己写了个ibatis3.0与spring集成的bean,运行还正常,还自鸣得意了一番,但是当独立使用ibatis时,在事务管理这个方面还是出现不少问题,所以还是打算再认真研究一番ibatis3.0

1.SqlSessionFactory 
每个ibatis应用都应该只有一个SqlSessionFactory的实例对象,所以一般设置为static属性或者使用spring管理时返回singleton类型,与spring集成时其实也是写一个怎样构建SqlSessionFactory的Bean, 
构建SqlSessionFactory一般是SqlSessionFactoryBuild通过读取ibatis的配置文件而进行build的: 
Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml"); 
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuild().build(reader);

配置文件SqlMapConfig.xml的一般结构(元素顺序不能变)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties" />
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="false" />
<setting name="useColumnLabel" value="true" />
<setting name="defaultExecutorType" value="SIMPLE" />
</settings>
<typeAliases>
<typeAlias alias="Person" type="test.Person"/>
</typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="jdbc">
<property name="" value="" />
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlMappers/Person.xml" />
<mapper resource="sqlMappers/UserShop.xml" />
</mappers>
</configuration>

<settings />是配置ibatis的具体行为属性的,

<typeAliases />是为了将较长的module类名简化,在<mappers />里可以使用 
<environment />是配置transaction manager和connection pooling的 
<mappers />是sql语句的构造地方,一般每个module对应一个文件

2.SqlSession 
可以从SqlSessionFactory得到SqlSession: sessionFactory.openSession(); 
SqlSession是一切Sql相关数据库操作的中心,insert,select,update,delete... 
SqlSession不是线程安全的(也就是有状态的),所以它的作用域最好是在一个Thread下,每个Thread有自己的SqlSession对象实例,彼此不相关. 
Never keep references to a SqlSession instance in a static field or even an instance field of a class.  Never keep references to a 
SqlSession in any sort of managed scope, such as HttpSession of of the Servlet framework.

默认sessionFacory.openSession()拿到的SqlSession不是自动commit的,所以如果是更新操作必须自己执行session.commit() 
关闭SqlSession很重要,必须保证在线程结束时关闭这个SqlSession,可以在finally中 
session.close(); 
那跟Spring集成是怎样做到这一点的呢,因为dataSource是由spring管理的,所以他可以保证在一个Thread的每个方法中拿到的Connection是同一个对象, 
虽然每个方法从sessionFactory.openSession()拿到的SqlSession对象是不同的,但是sqlSession对象中的connection是相同的,所以spring就可以在service层的方法结束之前将这个connection commit跟close,这样就实现了事务控制. 
我们往往在dao层是一个方法对应一个sql语句的,不在这里控制事务,控制事务应该在service层, dao的每个方法拿到的sqlsession对象都是不相同的(尽管它的connection可能相同). 
那我们应该怎样在没有spring的情况下实现ibatis的事务控制呢?还要保持dao的结构,以保持能跟spring随时切换? 
看来ThreadLocal要派上用场了 
---占位----

3.讲完了SqlSession这个大头,再来说说具体的配置信息 
配置文件结构 
configuration 
    properties 
    settings 
    typeAliases 
    typeHandlers 
    objectFactory 
    plugins 
    environments 
       environment 
           transactionManager 
           dataSource 
    mappers 
       
4.ibatis可以配置多个environment环境 
供开发,测试,上线等切换 
但是一个SqlSessionFactory只能对应一个environment, 
也就是 one SqlSessionFactory per database

5.transactionManager 
There are two TransactionManager types (i.e. type=”?????”) that are included with iBATIS: 
    JDBC – This configuration simply makes use of the JDBC commit and rollback facilities directly.  It relies on the connection retrieved from the dataSource to manage the scope of the transaction.   
    MANAGED  – This configuration simply does nothing, quite literally.  It never commits, rolls back or closes a connection.  Instead, it lets the container manage the full lifecycle of the transaction (e.g. Spring or a JEE Application Server context).

6.dataSource的配置 
类型可使用UNPOOLED,POOLED,JNDI三种

7.接下来是重头戏mappers 
这里是我们直接写sql的地方,ibatis在这里也花了最多功夫,特别是关于select的mapper.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper
PUBLIC "-//ibatis.apache.org//DTD mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="test.UserShop">
<insert ...> ... </insert>
<select ...> ... </select>
<update ...> ... </update>
<delete ...> ... </delete>
</mapper>

select 元素的所有的如下:

<select
id=""
parameterType=""
resultType=""
resultMap=""
flushCache=""
useCache=""
timeout=""
fetchSize=""
statementType=""
resultSetType="">

在Ibatis3中parameterMap已经不再使用。
(1).select 
<select id="getUser" parameterType="int" resultType="test.User"> 
       select * from user where userId = #{value} 
</select> 
注意#{value},resultType可以换成resultMap,这个resultMap就比较复杂了,也是最强大的工具,可以完成复杂的mapper(resultSet->object)

(2).insert,update,delete 
这几个操作都比较类似,返回的一般是受影响的行数. 
insert 可以返回auto_increament的值

<insert id="insertPerson" parameterType="Person"
useGeneratedKeys="true" keyProperty="userId">
insert into person(name,age) values(#{name},#{age})
</insert>

这样,传入的Person类对象的userId就会被set成auto_increament那个值.

(3).可以使用<sql id="columns">name,age</sql>构造可重用的sql片段 
这样就可以在那四个主要的元素里用<include refid="columns">引用这个常用sql片段

(4).resultMap很复杂,它可以处理一对一,一对多,多对多关系 
比如一个blog对应一个author, 一个blog对应多个post, 一个post对应多个comment 
resultMap的结构: 
resultMap 
    constructor (向java构造函数设置值) 
       idArg 
       arg 
    id (id result,同result) 
    result (字段映射注入) 
    association (一对一关系,它里面有自己的result映射) 
    collection  (一对多关系, 它里面有自己的result映射,和可能的collection) 
    discriminator

(5).association (一个Blog对应一个Author)

<resultMap id="blogResult" type="Blog">
<association property="author" column="blog_author_id" javaType="Author">
<id property="id" column="author_id" />
<result property="username" column="author_username" />
</associaton>
</resultMap>

当然association也可以使用 
<association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>

在Blog类定义里会有一个Author类字段,会自动装载数据 
private Author author;

(6).collection (一个Blog对应多个Post)

<resultMap id="blogResult" type="Blog">
<collection property="posts" column="blog_id" ofType="Post" javaType="ArrayList" resultMap="postResult" />
</resultMap>
collection也可以精简为
<collection property="posts" ofType="Post" resultMap="postResult" />
相就地,在Blog类定义里会有:
private List<Post> posts

8.cache

其实我是不打算在ibatis这层做cache的,一般cache还是在service层做. 
ibatis对于select才会进行cache,而我觉得这个时候cache没多大意义,因为多次請求相同的select語句(sql相同)而又没有进行表的相关update的情况并不多. 
但还是看看ibatis是怎样处理cache的 
要开启cache,需要在mapper文件中加上一句: <cache /> 
(1).cache所有select的結果 
(2).在同一mapper文件中的insert,update,delete会flush cache 
(3).cache使用least recently used(LRU)算法 
(4).cache没有定时flush的功能 
(5).cache保存1024个对象或list引用 
(6).cache是read/write cache, 从cache拿出对象不是共享的,caller可以任意修改而不用担心其他caller也拿到相同的对象(相同的reference)

9.动态SQL 
以前用jdbc时经常要根据输入条件而组装成不同的sql,这种就是动态sql 
ibatis的动态sql关键词:

if, choose(when,otherwise),trim(where,set),foreach
(1).if
<if test="title != null">
AND title like #{title}
</if>
<![CDATA[
]]>

(2).choose(when,otherwise)只选择其中一种情况

<select ...>
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND title like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>

(3).trim, where, set

<select id="findBlog" paramaterType="Blog" resultType="Blog">
select * from blog
<where>
<if test=”state != null”>
state = ${state}
</if>
<if test=”title != null”>
AND title like ${title}
</if>
<if test=”author != null and author.name != null”>
AND title like ${author.name}
</if>
</where>
</select> <update id="updateAuthorIfNecessary"
parameterType="domain.blog.Author">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>

(4).foreach

<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>

10.ibatis的annotation 
ibatis3.0也增加了annotation,当然主要还是用在mapper这个问题上 
个人感觉是鸡肋,暂时不会使用.

Mybayis的项目使用的Mapping文件使用总结参考(一)的更多相关文章

  1. mybayis项目使用的Mapping文件使用总结参考(二)

    针对in字句中的数组使用方法 <select id="getCpProfileNamesByIds" resultType="string"> se ...

  2. 使用mybatis-generator自动生成model、dao、mapping文件

    参考文献:http://www.cnblogs.com/smileberry/p/4145872.html 一.所需库 1.mybatis-generator库 2.连接DB的驱动(此以mysql为例 ...

  3. Android项目实战(二十四):项目包成jar文件,并且将工程中引用的jar一起打入新的jar文件中

    前言: 关于.jar文件: 平时我们Android项目开发中经常会用到第三方的.jar文件. 其实.jar文件就是一个类似.zip文件的压缩包,里面包含了一些源代码,注意的是.jar不包含资源文件(r ...

  4. ANDROID STDUIO 项目里的R文件突然丢失的解决办法N种之一

    刚刚项目里的R文件突然挂了,清理项目,关闭重开Studio,都不能解决.快没折了. 然后只好在项目上右击,看看有没有解决的办法.发现有个 Make Module ,姑且试试吧. 结果,竟然修复了.这是 ...

  5. chrome调试本地项目, 引用本地javascript文件

    chrome调试本地项目, 引用本地javascript文件 本地文件可以访问本地文件 修改快捷方式属性 C:\Users\xxx\AppData\Local\Google\Chrome\Applic ...

  6. 解决eclipse+git中每次clean项目需要重新commit文件

    使用.gitignore文件避免每次clean项目需要重新commit文件(XX.xcodeproj/project.xcworkspace/xcuserdata/XX.xcuserdatad/Use ...

  7. delphi项目中的modelsupport文件夹

    delphi项目中的modelsupport文件夹 今天写着写着突然发现多了一个这个文件夹..苦思不得其解  看着又难受  删了又重建 终于找到了  存此备查;Tools--option--toget ...

  8. iOS之多控制器管理--项目中的常见文件

    项目中的常见文件 内容大纲: 1.LaunchScreen 2.info.plist文件 3.pch文件 1.LaunchScreen xcode5和xcode6区别 1.xcode6没有Framew ...

  9. PTPX中的activity文件以及mapping文件

    在不同的simulation中的capturing switching activity: SAIF:Switching Activity Interface Format,包含toggle coun ...

随机推荐

  1. Django用户认证模块中继承AbstractUser与AbstractBaseUser重写User表的区别

    AbstractUser和AbstractBaseUser看起来十分相似,如果你不熟悉djiango的auth重写User,那你很容易弄错,导致一堆bug. 我们查看AbstractUser的源码得知 ...

  2. ######【Python】【基础知识】【一些未知的知识点】######

    在查资料.看书过程中遇到的一些未知的领域.知识点: 1.模仿静态变量 可参考: https://www.runoob.com/python/python-exercise-example41.html ...

  3. Python+requests重定向和追踪

    Python+requests重定向和追踪 一.什么是重定向 重定向就是网络请求被重新定个方向转到了其它位置 二.为什么要做重定向 网页重定向的情况一般有:网站调整(如网页目录结构变化).网页地址改变 ...

  4. INI配置文件格式解析

    INI配置文件有三要素parameters,sections和comments. 1.parameters 指一条配置,就像key = value这样的. 2.sections sections是pa ...

  5. Python初学者常见错误详解

    Python初学者常见错误详解 0.忘记写冒号 在 if.elif.else.for.while.class.def 语句后面忘记添加 “:”   if spam == 42 print('Hello ...

  6. hdu 1572 全排列的搜索

    好久没写搜索的题目了 复习一下/./ 这道题目是暴力的全排列#include<cstdio> #include<iostream> #include<cstring> ...

  7. 又谈F分布

    今天看到一篇不错的博文,有感,记录下来,相对来说讲到了本质,也很容易理解.https://www.cnblogs.com/think-and-do/p/6509239.html 首先,老生常谈,还是那 ...

  8. 关于ManualResetEvent的实例分析

    最近用WPF开发时使用多个定时器处理时需要实例化N多个DispatcherTimer,而且全部暴露在程序外部,显得很冗杂,例如下面的例子:用到的两个定时器就要实例化两个DispatcherTimer, ...

  9. GoBelieve service部署问题整理

  10. 转载一篇让你全面了解什么是.NET。

    转载于:https://www.52abp.com/BlogDetails/10009 阅读文本大概需要 8 分钟. 持续进化的 .NET 这张图即是一个学习的路线图同样他也是 .NET 平台的进化图 ...