以前用过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>

(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>

(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,主要还是推荐使用xml配置

Ibatis 3.0 之前使用的都是2.0 3.0与2.0的内容有很大的不同的更多相关文章

  1. Hadoop3.0新特性介绍,比Spark快10倍的Hadoop3.0新特性

    Hadoop3.0新特性介绍,比Spark快10倍的Hadoop3.0新特性 Apache hadoop 项目组最新消息,hadoop3.x以后将会调整方案架构,将Mapreduce 基于内存+io+ ...

  2. Zend Studio 12.0.2正式版发布和破解方法,zend studio 12.0.1汉化,相式设置为Dreamweaver,空格缩进为4个, 代码默认不折叠的设置,Outline中使用的图形标志,代码颜色之eot设置。

    背景:zend studio 12.0.2 修复了一个12.0.1的:  Fixed problem with referenced variables marked as undefined,我都说 ...

  3. 给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?

    题目:给定一个函数rand()能产生1到n之间的等概率随机数,问如何产生1到m之间等概率的随机数? 先把问题特殊化,例如原题变为给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一 ...

  4. Android 7.0 启动篇 — init原理(二)(转 Android 9.0 分析)

    ========================================================          ================================== ...

  5. Android 7.0 启动篇 — init原理(一)(转 Android 9.0 分析)

    ========================================================          ================================== ...

  6. Win7 64bit+Anaconda(3-5.0.1,Python3.6)+Pycharm(community-2017.3.3)+OpenCV(python‑3.4.0‑cp36‑cp36m)(转载)

    Anaconda(3-5.0.1,Python3.6)下载链接:https://pan.baidu.com/s/1bqFwLMB 密码:37ih Pycharm(community-2017.3.3) ...

  7. Atitit.你这些项目不都是模板吗?不是原创  集成和整合的方式大总结

    Atitit.你这些项目不都是模板吗?不是原创  集成和整合的方式大总结 1.1. 乔布斯的名言:创新即整合(Creativity is just connecting things).1 1.2. ...

  8. 在vue中无论使用router-link 还是 @click事件,发现都没法从列表页点击跳转到内容页去

    在vue中如论使用router-link 还是 @click事件,发现都没法从列表页点击跳转到内容页去,以前都是可以的,想着唯一不同的场景就是因为运用了scroll组件(https://ustbhua ...

  9. Java1.0的AWT(旧AWT)和Java1.1以后的AWT(新AWT)有着很大的区别

    Java1.0的AWT(旧AWT)和Java1.1以后的AWT(新AWT)有着很大的区别,新的AWT克服了旧AWT的很多缺点,在设计上有较大改进,使用也更方便,这里主要介绍新的AWT, 但在Java1 ...

随机推荐

  1. spring @Component

    使用 @Component <context:component-scan base-package="dao" />   虽 然我们可以通过@Autowired或@R ...

  2. perfect-scrollbar示例

    <!DOCTYPE html> <html> <head> <title>perfect-scrollbar - www.97zzw.com -97站长 ...

  3. hdu 5344 MZL's xor

    MZL's xor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  4. HDOJ3743<分治>

    题意:求一个排列的逆序数. #include<cstdio> #include<iostream> #include<algorithm> const int ma ...

  5. servlet中路径的获取

    1.获取项目的绝对路径 可以request.getRealPath("/"),但是这个方法已经废弃了,最好用this.getServletContext().getRealPath ...

  6. UIImageView 的contentMode属性 浅析

    UIImageView 的contentMode这个属性是用来设置图片的显示方式,如居中.居右,是否缩放等,有以下几个常量可供设定:UIViewContentModeScaleToFillUIView ...

  7. WebSocket学习笔记——无痛入门

    WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报  分类: 物联网学习笔记(37)  版权声明:本文为博主原 ...

  8. 河南多校联合训练 F 不是匹配

    描述  有N个人,N个活动, 每个人只会对2个或者3个活动感兴趣,  每个活动也只有两个人或者两个活动对它兴趣,每个人参加一个  感兴趣的活动需要一天 ,且当天该活动被参加时,其他的人不能参加  如果 ...

  9. 多校 Robot Motion

    题目链接:http://acm.hust.edu.cn/vjudge/contest/124435#problem/J 密码:acm Sample Input NEESWE WWWESS SNWWWW ...

  10. Swift学习(1)

    swif(1) println("Hello, world") 输出结果: Hello, world swift使用let来声明常量,使用var来声明变量 //变量 var myV ...