Ibatis 3.0 之前使用的都是2.0 3.0与2.0的内容有很大的不同


以前用过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" ?>
    PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"     
    "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">



















   
   










 


是配置ibatis的具体行为属性的,
是为了将较长的module类名简化,在里可以使用
是配置transaction manager和connection pooling的
是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"?>
PUBLIC "-//ibatis.apache.org//DTD mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">


   ...
  
   ...
   ...


(1).select

注意#{value},resultType可以换成resultMap,这个resultMap就比较复杂了,也是最强大的工具,可以完成复杂的mapper(resultSet->object)

(2).insert,update,delete
这几个操作都比较类似,返回的一般是受影响的行数.
insert 可以返回auto_increament的值
useGeneratedKeys="true" keyProperty="userId">
insert into person(name,age) values(#{name},#{age})

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

(3).可以使用name,age构造可重用的sql片段
这样就可以在那四个主要的元素里用引用这个常用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)

   
       
       
   

当然association也可以使用


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

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

   

collection也可以精简为

相就地,在Blog类定义里会有:
private List posts


8.cache
其实我是不打算在ibatis这层做cache的,一般cache还是在service层做.
ibatis对于select才会进行cache,而我觉得这个时候cache没多大意义,因为多次請求相同的select語句(sql相同)而又没有进行表的相关update的情况并不多.
但还是看看ibatis是怎样处理cache的
要开启cache,需要在mapper文件中加上一句:
(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

   AND title like #{title}
   

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


(3).trim, where, set
   

          parameterType="domain.blog.Author">
    update Author
     
        username=#{username},
        password=#{password},
        email=#{email},
        bio=#{bio}
     

    where id=#{id}


(4).foreach



10.ibatis的annotation
ibatis3.0也增加了annotation,主要还是推荐使用xml配置

相关