zoukankan      html  css  js  c++  java
  • Mybatis高级映射、动态SQL及获得自增主键

    原文:http://www.cnblogs.com/edwinchen/p/4105278.html

    相信大家在用mybatis操作数据库时时都会碰到一个问题,假如现在我们有一个关于作者的list authorList,需要根据authorList里已有的作者信息在数据库中查询相应作者的博客信息。那么最容易想到的做法就是遍历authorList,获取相应的信息查询数据库。

        

    复制代码
    for(int i=0;I < authorList.size();i++) {
            ……
    
            //查询数据库代码
    
            //select * from blog where author=#{author,jdbcType=VARCHAR}
    
    }
    复制代码

    想一想,如果假设authorList的长度为N,那么我们就需要查询N次数据库,如果用这种方法,程序的开销不仅仅是查询,还有从数据库连接池中取出连接实例、建立数据库连接、将数据库实例返还给数据库连接池,假设这三个动作加起来总共用时0.001秒。那么采取遍历的办法查询,将会多耗时0.001N秒,如果需要查询1000次,那么将多1秒钟的时间,对于程序猿来说,这是不可忍受的,因为这只是一个循环查询,还不算其它的业务代码。

    那么,有没有更好的办法呢,答案是肯定,其中之一是动态SQL:

    先上代码:

       

    复制代码
     <select id="dynamicForeachTest" resultType="com.blog.Blog" parameterType="java.util.List">
    
        select * from blog where author in
    
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
    
            #{item}
    
        </foreach>
    
    </select>        
    复制代码

    tem表示集合中每一个元素进行迭代时的别名,

    index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,

    open表示该语句以什么开始,

    separator表示在每次进行迭代之间以什么符号作为分隔符,

    close表示以什么结束这样返回值就可以用List<Bolg>接受.

    但是动态SQL中的foreach语句用的最多的实在insert语句中,并且通常在in子句中使用。

    二、高级映射

    在使用mybatis的时候,一般是使用resultType = com.blog.author 实体类来接受查询结果

    或者是使用resultType = java.util.map将数据库列名作为key,记录值作为value返回。

    但是这次需要使用resultMap,它可以允许自由组合返回值的形式,用以处理更复杂的查询。

    还是先上代码:

    SQL:

        

    复制代码
    <select id="getBlogs" resultMap=" blogs " parameterType="map">
        Select a.authorID,
                a.uthorName,
                b.blogID,
                b.blogName
        from author a left join blog b on a. authorID=b. authorID                       where a. authorID = #{authorID,jdbcType=INTEGER}
    </select>              
    复制代码

    mybatis配置:

    复制代码
        <resultMap id="blogs" type="com.bloh.Blog">
    
            <id property="authorID" column=" authorID">
    
            <result property="authorName" column=" authorName">
    
            <collection property="postsList" ofType="com.bolg.Post">
    
                <id property="blogID" column=" blogID"/>
    
                <result property="blogName" column="blogName"/>
    
            </collection>
    
        </resultMap>
    复制代码

    Blog实体类

    复制代码
    Public class Bolg {
    
        private Integer authorID;
    
        private String authorName;
    
        private List<Post> postsList;
    
        //setter getter
    
    }
    复制代码

    Post实体类

    复制代码
    Public class Post {
    
        private Integer blogID;
    
        private String blogName;
    
        //setter getter
    
    }
    复制代码

    这样就可以用一个实体接受一个复杂查询了。

    下面再介绍下各个属性的作用:

    其它和普通mybatis查询的属性和配置就不细说了,

    resultMap用来代替resultType,表示查询结果返回的格式

    resultMap中的id主要有两个作用:

    1. 类似索引,提高查询性能
    2. 区分不同结果

    所以id最好不要省略,如果没有主键,用能唯一区分记录的字段代替

    result即实体类中定义的变量名,column是数据库的列名

    collection 就是列表、map等集合

        postsList就是在Blog实体类中定义的list变量名

        ofType就是对象列表中对象的实体类。

    三、获得自增ID:

        如果有如下情况,在插入数据库记录后,想得到插入记录的主键,用以后面的业务代码

    那么mybatis针对这种情况也提供了相应的支持(不支持批量插入):

    MySQL是原声自增ID;假设自增主键的字段名就为ID

    复制代码
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="User">
    
    insert into <include refid="TABLE_NAME" /> ( NAME, AGE )
    
    values ( #{name}, #{age} )
    
    </insert>
    复制代码

    比普通的插入就多了两个属性 useGeneratedKeys="true" 表示开启返回自增ID

    keyProperty="id" 表示返回主键的名字。

    那么在业务代码中就可以用下列语句接收:

    假设实体类为User

    User userNew = userMapper.insert(user);
    
    userNew.getID //即为插入后的自增ID

    其实,mysql的自增主键可以用select LAST_INSERT_ID();来得到,

    所以,还有一种写法:

    复制代码
    <insert id="insert" parameterType="User">
    
    <selectKey resultType="int" order="AFTER" keyProperty="id">
    SELECT LAST_INSERT_ID() AS id
    </selectKey>
    
    insert into name,age
    
    values ( #{name}, #{age} )
    
    </insert>
    复制代码

    和mysql的获取主键方式刚好相反,mysql是insert执行后由表分配自增长的值,而oracle是获取到自增长的值后再进行插入记录操作,在执行insert sql前必须指定一个主键值给要插入的记录所以要要在"BEFORE"的时候拿到自增的序列,然后用selectKey的方式注入到入参映射中即可。假设自增长还是id

    复制代码
    <insert id=" insert " useGeneratedKeys="true" keyProperty="id" parameterType="xxxx" >
    
    <selectKey resultType="int" order="BEFORE" keyProperty="id">
    
    SELECT SEQ_TABLE.NEXTVAL FROM dual
    
    </selectKey>
    
    INSERT INTO id,name,age
    
    VALUES
    
    (#{id} #{name}, #{age} )
    
    </insert>
    复制代码

    这里的id就是selectKey获得的自增id。

    接收方式和mysql一样,在获取自增主键时,最好使用实体接收。

    作者<ahref="http: www.cnblogs.com="" edwinchen="" "="" target"_blank"="">瞪着太阳的乌鸦

  • 相关阅读:
    cocos2dx 2.0 学习笔记简单动画
    几种插入数据的方法
    c#中如何获取本机用户名、MAC地址、IP地址、硬盘ID、CPU序列号、系统名称、物理内存
    C#高效编程改进C#代码的50个行之有效的办法摘抄笔记
    获取两个日期之间的每一天
    取SQL中某个字段的后两位
    该行已经属于另一个表 的解决办法
    一个实体对象不能由多个 IEntityChangeTracker 实例引用
    MVC返回JSON,IE下无法接收JSON,IE下JSON提示另存为
    entity framework DbContext Attach判断
  • 原文地址:https://www.cnblogs.com/joycelishanhe/p/4494955.html
Copyright © 2011-2022 走看看