zoukankan      html  css  js  c++  java
  • Mybayis的项目使用的Mapping文件使用总结参考(一)

    作者: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这个问题上 
    个人感觉是鸡肋,暂时不会使用.

  • 相关阅读:
    人肉搜索利大于弊?
    上海美容美发连锁店疯狂扩展,大面值会员卡慎办
    jQuery简单入门
    把苦难装在心里《赢在中国》(20080527)
    赢在中国(080304)
    ASP.NET MVC Preview 2新特性
    Lucifer的一场暴强围英雄表演
    php pack、unpack、ord 函数使用方法(二进制流接口应用实例)
    PHP开发绝对不能违背的安全铁则(摘)
    MySQL数据类型:UNSIGNED注意事项
  • 原文地址:https://www.cnblogs.com/lxl57610/p/7399184.html
Copyright © 2011-2022 走看看