首页 > 代码库 > 映射文件

映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zln.mapper.StudentMapper">

    <!--配置给定命名空间的缓存-->
    <!--<cache></cache>-->

    <!--从其他命名空间引用缓存配置-->
    <!--<cache-ref namespace=""/>-->

    <!--结果集映射-->
    <resultMap id="StudentResultMap" type="Student">
        <id property="studId" column="stud_id" jdbcType="INTEGER"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="dob" column="dob" jdbcType="DATE"/>
    </resultMap>

    <!--可重用的SQL片段-->
    <sql id="selectStudents">
        SELECT stud_id,name,email,dob
    </sql>


    <select id="findAllStudents" resultMap="StudentResultMap">
        <include refid="selectStudents"/>
        FROM Student
    </select>
    <!--
    select详解
        id:查询id,如果使用Mapper形式编写,那么id值就是Mapper接口的方法名
        parameterType:参数类型,一般就是一个pojo对象 或者 基本数据类型 或者 map 等
        resultType:结果集映射类型
        resultMap:结果集映射类型
        flushCache:默认false,如果为true:无论语句何时被调用,都会导致缓存情况
        timeout:超时时间
        fetchSize:默认由驱动决定,每次批量返回的行数
        statementType:STATEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。 默认值:PREPARED。
        resultSetType:FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE中的一种。默认是不设置(驱动自行处理)。
    -->
    <!--
    #{property,javaType=int,jdbcType=NUMERIC},用这种方式来指定参数类型,一般如果是pojo,MyBatis是能够自动获取的
    和iBatis一样,也有
    ${} 这种写法,一般用于 order by
    -->
    <!--
    一对一映射:在resultMap中配置association
    一对多映射:配置collection
    -->

    <!--
    缓存:默认情况没开启缓存
    SQL映射文件中加上 <cache/> 就会开启二级缓存
    -->


    <!--
    if标签 where标签 trim标签

    <select id="selectBySelective" resultType="xxx.UserInfo">
        select
        <include refid="Base_Column_List"/>
        from uc_user
        <where>
            (
            <if test="userName != null">
                user_name = #{userName}
            </if>
            <if test="email != null">
                or email = #{email}
            </if>
            <if test="phone != null">
                or phone = #{phone}
            </if>
            <if test="weiboId != null">
                or weibo_id = #{weiboId}
            </if>
            <if test="wxId != null">
                or wx_id = #{wxId}
            </if>
            <if test="qqId != null">
                or qq_id = #{qqId}
            </if>)
        </where>
        and status = 1
    </select>
    这样代码看似没有什么问题但是其实是有问题的。为什么呢?
    如果userName 为空,后面某字段不为空,最后的sql语言会成为这样:
    select * from uc_user where(or email = "xxx") and status = 1

    使用mybatis < where > 标签就是为了防止这种情况,mybatis会在第一个
userName 为空的情况下,帮我们去掉后面的语句的第一个”or”

但是我加了where标签中加入()后,语句会报错。因为自动去掉”or”会失效。

查看了mybatis官方文档发现了另一个标签 < trim >可以通过自定义 trim 元素来定制我们想要的功能

trim标签包围的内容可以设置几个属性:
prefix :内容之前加的前缀
suffix :内容之后加的后缀
prefixOverrides: 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的,多个忽略序列用“|”隔开)。它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除。


-->
    <!--
    <select id="selectBySelective" resultType="xxx.UserInfo">
        select
        <include refid="Base_Column_List"/>
        from uc_user
        <trim prefix="WHERE (" suffix=")" prefixOverrides="AND |OR ">
            <if test="userName != null">
                user_name = #{userName}
            </if>
            <if test="email != null">
                or email = #{email}
            </if>
            <if test="phone != null">
                or phone = #{phone}
            </if>
            <if test="weiboId != null">
                or weibo_id = #{weiboId}
            </if>
            <if test="wxId != null">
                or wx_id = #{wxId}
            </if>
            <if test="qqId != null">
                or qq_id = #{qqId}
            </if>
        </trim>
        and status = 1
    </select>
-->

    <!--choose  when  -->
    <!--
    <select id="getStudentListChooseEntity" parameterType="StudentEntity" resultMap="studentResultMap">
        SELECT * from STUDENT_TBL ST
        <where>
            <choose>
                <when test="studentName!=null and studentName!=‘‘ ">
                    ST.STUDENT_NAME LIKE CONCAT(CONCAT(‘%‘, #{studentName}),‘%‘)
                </when>
                <when test="studentSex!= null and studentSex!= ‘‘ ">
                    AND ST.STUDENT_SEX = #{studentSex}
                </when>
                <when test="studentBirthday!=null">
                    AND ST.STUDENT_BIRTHDAY = #{studentBirthday}
                </when>
                <when test="classEntity!=null and classEntity.classID !=null and classEntity.classID!=‘‘ ">
                    AND ST.CLASS_ID = #{classEntity.classID}
                </when>
                <otherwise>

                </otherwise>
            </choose>
        </where>
    </select>
    -->

    <!--foreach 循环标签-->
    <!--
    <select id="getStudentListByClassIDs" resultMap="studentResultMap">
        SELECT * FROM STUDENT_TBL ST
        WHERE ST.CLASS_ID IN
        <foreach collection="list" item="classList"  open="(" separator="," close=")">
            #{classList}
        </foreach>
    </select>
    -->


    <!--SET 更新-->
    <!--
    <update id="updateUserInfoBySet" parameterType="userInfo">
        update userInfo
        <set>
            <if test="mobile!=null">
                mobile=#{mobile},
            </if>
            <if test="gender!=null">
                gender=#{gender},
            </if>
            <if test="position!=null">
                position = #{position},
            </if>
        </set>
        where userid=#{userid}
    </update>
    a.SQL语句的set被<set>标签替代。
    b.每个<if>中语句最后都带有逗号,如果有写过SQL语句的同学就一定知道,最后的逗号是不能有的,因此,这里的<set>标签能够帮助我们自动的移除最后一个<if>中的逗号。
    c.<trim>是一个非常强大的标签,因此,我们也可以通过<trim>来实现<set>的功能,如下:【这种写法的运行效果与<set>等价】
    -->
    <!--
    <update id="updateUserInfoBySet" parameterType="userInfo">
        update userInfo
        <trim prefix="SET" suffixOverrides=",">
            <if test="mobile!=null">
                mobile=#{mobile},
            </if>
            <if test="gender!=null">
                gender=#{gender},
            </if>
            <if test="position!=null">
                position = #{position},
            </if>
        </trim>
        where userid=#{userid}
    </update>
    -->
</mapper>

@font-face { font-family: "Courier New"; }@font-face { font-family: "Times"; }@font-face { font-family: "宋体"; }@font-face { font-family: "Cambria Math"; }@font-face { font-family: "@宋体"; }@font-face { font-family: "Calibri Light"; }@font-face { font-family: "Calibri"; }@font-face { font-family: "MS Mincho"; }@font-face { font-family: "Consolas"; }@font-face { font-family: "微软雅黑,Bold"; }@font-face { font-family: "Helvetica Neue"; }@font-face { font-family: "微软雅黑"; }@font-face { font-family: "Consolas,Bold"; }@font-face { font-family: "SimSun"; }@font-face { font-family: "@SimSun"; }@font-face { font-family: "@MS Mincho"; }@font-face { font-family: "@微软雅黑"; }p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0cm 0cm 0.0001pt; text-align: justify; font-size: 12pt; font-family: Calibri; }h1 { margin: 17pt 0cm 16.5pt; text-align: justify; line-height: 240%; page-break-after: avoid; font-size: 22pt; font-family: Calibri; font-weight: bold; }h2 { margin: 13pt 0cm; text-align: justify; line-height: 173%; page-break-after: avoid; font-size: 16pt; font-family: "Calibri Light"; font-weight: bold; }h3 { margin: 13pt 0cm; text-align: justify; line-height: 173%; page-break-after: avoid; font-size: 16pt; font-family: Calibri; font-weight: bold; }p.MsoDocumentMap, li.MsoDocumentMap, div.MsoDocumentMap { margin: 0cm 0cm 0.0001pt; text-align: justify; font-size: 12pt; font-family: "Times New Roman"; }p { margin-right: 0cm; margin-left: 0cm; font-size: 12pt; font-family: "Times New Roman"; }pre { margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; }p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph { margin: 0cm 0cm 0.0001pt; text-align: justify; text-indent: 21pt; font-size: 12pt; font-family: Calibri; }span.a { font-family: "Times New Roman"; }span.HTML { font-family: "Courier New"; }span.tag { }span.pln { }span.atn { }span.pun { }span.atv { }span.apple-converted-space { }span.kwd { }span.typ { }span.com { }span.lit { }span.str { }.MsoChpDefault { font-family: Calibri; }div.WordSection1 { }ol { margin-bottom: 0cm; }ul { margin-bottom: 0cm; }

cache

配置给定命名空间的缓存。 ?

cache-ref

从其他命名空间引用缓存配置。 ?

resultMap

最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载你的对象。 ?     ?

<resultMap id="StudentResult" type="com.mybatis3.domain.Student">

  <id property="studId" column="stud_id" />

  <result property="name" column="name" />

  <result property="email" column="email" />

  <result property="phone" column="phone" />

</resultMap>

<select id="findAllStudents" resultMap="StudentResult">

    SELECT * FROM STUDENTS

</select>

<select id="findStudentById" parameterType="int" resultMap="StudentResult">

    SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}

</select>

 

拓展 ResultMap 

我们可以从从另外一个<resultMap>,拓展出一个新的<resultMap>,这样,原先的属性映射可以继承过来,以实现。 

 

  1. <resultMap type="Student" id="StudentResult">
  2.   <id property="studId" column="stud_id" />
  3.   <result property="name" column="name" />
  4.   <result property="email" column="email" />
  5.   <result property="phone" column="phone" />
  6. </resultMap>
  7. <resultMap type="Student" id="StudentWithAddressResult" extends="StudentResult">
  8.   <result property="address.addrId" column="addr_id" />
  9.   <result property="address.street" column="street" />
  10. 10.   <result property="address.city" column="city" />
  11. 11.   <result property="address.state" column="state" />
  12. 12.   <result property="address.zip" column="zip" />
  13. 13.   <result property="address.country" column="country" />

14. </resultMap>

 

一对一

  1. public class Address
  2.         {
  3.             private Integer addrId;
  4.             private String street;
  5.             private String city;
  6.             private String state;
  7.             private String zip;
  8.             private String country;
  9.             // setters & getters
  10. 10.         }

 

  1. public class Student
  2.         {
  3.             private Integer studId;
  4.     private String name;
  5.     private String email;
  6.     private PhoneNumber phone;
  7.     private Address address;
  8.     //setters & getters
  9. }

 

 

  1. <resultMap type="Student" id="StudentWithAddressResult">
  2.   <id property="studId" column="stud_id" />
  3.   <result property="name" column="name" />
  4.   <result property="email" column="email" />
  5.   <result property="phone" column="phone" />
  6.   <result property="address.addrId" column="addr_id" />
  7.   <result property="address.street" column="street" />
  8.   <result property="address.city" column="city" />
  9.   <result property="address.state" column="state" />
  10. 10.   <result property="address.zip" column="zip" />
  11. 11.   <result property="address.country" column="country" />

12. </resultMap>

 

  1. <select id="selectStudentWithAddress" parameterType="int"
  2. resultMap="StudentWithAddressResult">
  3.     SELECT STUD_ID, NAME, EMAIL, A.ADDR_ID, STREET, CITY, STATE,
  4.         ZIP, COUNTRY
  5. FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID
  6.     WHERE STUD_ID=#{studId}
  7. </select>

 

 

我们可以使用圆点记法为内嵌的对象的属性赋值。在上述的 resultMap 中,Student 的 address 属性使用了圆点记法 被赋上了 address 对应列的值。

 

上述样例展示了一对一关联映射的一种方法。然而,使用这种方式映射,如果 address 结果需要在其他的 SELECT 映射 语句中映射成 Address 对象,我们需要为每一个语句重复这种映射关系。MyBatis提供了更好地实现一对一关联映射的方 法:嵌套结果 ResultMap 和嵌套 select 查询语句。接下来,我们将讨论这两种方式。 

 

 

使用嵌套结果 ResultMap 实现一对一关系映射

 

  1. <resultMap type="Address" id="AddressResult">
  2.   <id property="addrId" column="addr_id" />
  3.   <result property="street" column="street" />
  4.   <result property="city" column="city" />
  5.   <result property="state" column="state" />
  6.   <result property="zip" column="zip" />
  7.   <result property="country" column="country" />
  8. </resultMap>
  9. <resultMap type="Student" id="StudentWithAddressResult">
  10. 10.   <id property="studId" column="stud_id" />
  11. 11.   <result property="name" column="name" />
  12. 12.   <result property="email" column="email" />
  13. 13.   <association property="address" resultMap="AddressResult" />

14. </resultMap>

15. <select id="findStudentWithAddress" parameterType="int" resultMap="StudentWithAddressResult">

16. SELECT STUD_ID, NAME, EMAIL, A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY

17. FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID

  1. 18.     WHERE STUD_ID=#{studId}

19. </select>

 

我们也可以使用<association 定义内联的 resultMap,代码如下所示: 

 

  1. <resultMap type="Student" id="StudentWithAddressResult">
  2.   <id property="studId" column="stud_id" />
  3.   <result property="name" column="name" />
  4.   <result property="email" column="email" />
  5.   <association property="address" javaType="Address">
  6.     <id property="addrId" column="addr_id" />
  7.     <result property="street" column="street" />
  8.     <result property="city" column="city" />
  9.     <result property="state" column="state" />
  10. 10.     <result property="zip" column="zip" />
  11. 11.     <result property="country" column="country" />
  12. 12.   </association>

13. </resultMap>

 

使用嵌套查询实现一关系映射 

 

  1. <resultMap type="Address" id="AddressResult">
  2.   <id property="addrId" column="addr_id" />
  3.   <result property="street" column="street" />
  4.   <result property="city" column="city" />
  5.   <result property="state" column="state" />
  6.   <result property="zip" column="zip" />
  7.   <result property="country" column="country" />
  8. </resultMap>
  9. <select id="findAddressById" parameterType="int" resultMap="AddressResult">
  10. 10.     SELECT * FROM ADDRESSES WHERE ADDR_ID=#{id}

11. </select>

12. <resultMap type="Student" id="StudentWithAddressResult">

  1. 13.   <id property="studId" column="stud_id" />

14. <result property="name" column="name" />

  1. 15.   <result property="email" column="email" />
  2. 16.   <association property="address" column="addr_id" select="findAddressById" />

17. </resultMap>

18. <select id="findStudentWithAddress" parameterType="int"

19. resultMap="StudentWithAddressResult">

  1. 20.     SELECT * FROM STUDENTS WHERE STUD_ID=#{Id}

21. </select>

 

在此方式中,<association>元素的 select属性被设置成了id为 findAddressById的语句。这里,两个分开的 SQL 语句将会在数据库中执行,第一个调用 findStudentById 加载 student 信息,而第二个调用 findAddressById 来 加载 address 信息。

Addr_id 列的值将会被作为输入参数传递给 selectAddressById 语句。 

 

 

一对多

  1. public class Course
  2. {
  3.     private Integer courseId;
  4.     private String name;
  5.     private String description;
  6.     private Date startDate;
  7.     private Date endDate;
  8.     private Integer tutorId;
  9.     //setters & getters

10. }

11. public class Tutor

12. {

  1. 13.     private Integer tutorId;
  2. 14.     private String name;
  3. 15.     private String email;
  4. 16.     private Address address;
  5. 17.     private List<Course> courses;
  6. 18.     / setters & getters

19. }

 

  1. <resultMap type="Course" id="CourseResult">
  2.   <id column="course_id" property="courseId" />
  3.   <result column="name" property="name" />
  4.   <result column="description" property="description" />
  5.   <result column="start_date" property="startDate" />
  6.   <result column="end_date" property="endDate" />
  7. </resultMap>
  8. <resultMap type="Tutor" id="TutorResult">
  9.   <id column="tutor_id" property="tutorId" />
  10. 10.   <result column="tutor_name" property="name" />
  11. 11.   <result column="email" property="email" />
  12. 12.   <collection property="courses" resultMap="CourseResult" />

13. </resultMap>

14. <select id="findTutorById" parameterType="int" resultMap="TutorResult">

15. SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL, C.COURSE_ID,

16. C.NAME, DESCRIPTION, START_DATE, END_DATE

17. FROM TUTORS T LEFT OUTER JOIN ADDRESSES A ON T.ADDR_ID=A.ADDR_ID

18. LEFT OUTER JOIN COURSES C ON T.TUTOR_ID=C.TUTOR_ID

19. WHERE T.TUTOR_ID=#{tutorId}

20. </select>

 

这里我们使用了一个简单的使用了 JOINS 连接的 Select 语句获取讲师及其所教课程信息。<collection>元素的 resultMap 属性设置成了 CourseResult,CourseResult 包含了 Course对象属性与表列名之间的映射。 

 

使用嵌套 Select 语句实现一对多映射 

 

  1. <resultMap type="Course" id="CourseResult">
  2.   <id column="course_id" property="courseId" />
  3.   <result column="name" property="name" />
  4.   <result column="description" property="description" />
  5.   <result column="start_date" property="startDate" />
  6.   <result column="end_date" property="endDate" />
  7. </resultMap>
  8. <resultMap type="Tutor" id="TutorResult">
  9.   <id column="tutor_id" property="tutorId" />
  10. 10.   <result column="tutor_name" property="name" />
  11. 11.   <result column="email" property="email" />
  12. 12.   <association property="address" resultMap="AddressResult" />
  13. 13.   <collection property="courses" column="tutor_id" select="findCoursesByTutor" />

14. </resultMap>

15. <select id="findTutorById" parameterType="int" resultMap="TutorResult">

  1. 16.     SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL
  2. 17.     FROM TUTORS T WHERE T.TUTOR_ID=#{tutorId}

18. </select>

19. <select id="findCoursesByTutor" parameterType="int" resultMap="CourseResult">

  1. 20.    SELECT * FROM COURSES WHERE TUTOR_ID=#{tutorId}

21. </select>

 

在这种方式中,<aossication>元素的 select 属性被设置为 id 为 findCourseByTutor 的语句,用来触发单独 的 SQL 查询加载课程信息。tutor_id 这一列值将会作为输入参数传递给findCouresByTutor 语句。 

 

 

 

 

sql

可以重用的 SQL 块,也可以被其他语句引用。 ?

<sql id=”userColumns”> id,username,password </sql>

<select id=”selectUsers” parameterType=”int” resultType=”hashmap”>

select <include refid=”userColumns”/> from some_table?where id = #{id}

</select>

 

insert

映射插入语句 ?

允许的属性

id

parameterType

flushCache

statementType

keyProperty

(仅对 insert 有用)标记一个属性,MyBatis 会通过 getGeneratedKeys 或者通过 insert 语句的 selectKey 子元素设置它的值。默认:不设置。

useGeneratedKeys

(仅对 insert 有用)这会告诉 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据(比如:像 MySQL 和 SQL Server 这样的数据库管理系统的自动递增字段)内部生成的主键。 默认值:false。

<insert id="insertAuthor" parameterType="domain.blog.Author" useGeneratedKeys=”true” keyProperty=”id”>?insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio})

</insert>

 

自定义生成一条主键、也可以是Oracle的序列

<insert id="insertAuthor" parameterType="domain.blog.Author">

<selectKey keyProperty="id" resultType="int" order="BEFORE">

select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1

</selectKey>?

insert into Author?(id, username, password, email,bio, favourite_section)?values?(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR}?)

</insert>

 

  1. <insert id="insertStudent" parameterType="Student">
  2.     <selectKey keyProperty="studId" resultType="int" order="BEFORE">
  3.         SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL
  4.     </selectKey>
  5.     INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
  6.         VALUES(#{studId},#{name},#{email},#{phone})
  7. </insert>

 

这里我们使用了<selectKey>子元素来生成主键值,并将值保存到 Student 对象的 studId 属性上。 属性 order=“before”表示 MyBatis 将取得序列的下一个值作为主键值,并且在执行 INSERT SQL 语句之前将值设置到 studId 属性上。

我们也可以在获取序列的下一个值时,使用触发器(trigger)来设置主键值,并且在执行INSERT SQL语句之 前将值设置到主键列上。如果你采取这样的方式,则对应的 INSERT 映射语句如下所示: 

 

  1. <insert id="insertStudent" parameterType="Student">
  2.     INSERT INTO STUDENTS(NAME,EMAIL, PHONE)
  3.         VALUES(#{name},#{email},#{phone})
  4.     <selectKey keyProperty="studId" resultType="int" order="AFTER">
  5.         SELECT ELEARNING.STUD_ID_SEQ.CURRVAL FROM DUAL
  6.     </selectKey>
  7. </insert>

 

 

 

timeout

 

update

映射更新语句 ?

id

parameterType

flushCache

statementType

timeout

 

delete

映射删除语句 ?

id

parameterType

flushCache

statementType

timeout

 

select

映射查询语句 ?

select允许的属性

id

唯一标识这条SQL,一般是Mapper接口的方法名

parameterType

参数的全限定名或别名

可以是自定义对象或int、map等

resultType

返回类型

resultMap

返回类型

resultMap的值是一个自己配置过的Map

flushCache

默认false

useCache

默认true

timeout

超时时间,默认不做处理

fetchSize

每次批量返回的行数

默认不做处理,由驱动自行决定

statementType

STATEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis 使用选择使用 Statement,PreparedStatement 或 CallableStatement。 默认值:PREPARED。

resultSetType

FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE

中的一种。默认是不设置(驱动自行处理)。

 

参数

#{id}

#{id,jdbcType=NUMERIC,javaType=int}

#{user.id}

#{id,jdbcType=NUMERIC,javaType=int,typehandler=myhandler}

${sql},注意:这种形式可能引发SQL注入问题

 

动态SQL标签

if

  1. <resultMap type="Course" id="CourseResult">
  2.   <id column="course_id" property="courseId" />
  3.   <result column="name" property="name" />
  4.   <result column="description" property="description" />
  5.   <result column="start_date" property="startDate" />
  6.   <result column="end_date" property="endDate" />
  7. </resultMap>
  8. <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"></select>
  9.     SELECT * FROM COURSES
  10. 10.         WHERE TUTOR_ID= #{tutorId}
  11. 11.     <if test="courseName != null">
  12. 12.     AND NAME LIKE #{courseName}
  13. 13.     </if>
  14. 14.     <if test="startDate != null">
  15. 15.     AND START_DATE >= #{startDate}
  16. 16.     </if>
  17. 17.     <if test="endDate != null">
  18. 18.     AND END_DATE <= #{endDate}
  19. 19.     </if>

20. </select>



  1. <select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
  2.     SELECT * FROM COURSES
  3.     <choose>
  4.         <when test="searchBy == ‘Tutor‘">
  5.             WHERE TUTOR_ID= #{tutorId}
  6.         </when>
  7.         <when test="searchBy == ‘CourseName‘">
  8.             WHERE name like #{courseName}
  9.         </when>
  10. 10.         <otherwise>
  11. 11.             WHERE TUTOR start_date >= now()
  12. 12.         </otherwise>
  13. 13.     </choose>

14. </select>



MyBatis 计算<choose>测试条件的值,且使用第一个值为 TRUE 的子句。如果没有条件为 true,则使用<otherwise> 内的子句。 

 

 

Where 

有时候,所有的查询条件(criteria)应该是可选的。在需要使用至少一种查询条件的情况下,我们应该使用 WHERE 子句。并且, 如果有多个条件,我们需要在条件中添加AND或OR。MyBatis提供了<where>元素支持这种类型的动 态 SQL 语句。

在我们查询课程界面,我们假设所有的查询条件是可选的。进而,当需要提供一个或多个查询条件时,应该改使用 WHERE 子句。 

  1. <select id="searchCourses" parameterType="hashmap"
  2. resultMap="CourseResult">
  3.     SELECT * FROM COURSES
  4.     <where>
  5.         <if test=" tutorId != null ">
  6.             TUTOR_ID= #{tutorId}
  7.         </if>
  8.         <if test="courseName != null">
  9.             AND name like #{courseName}
  10. 10.         </if>
  11. 11.         <if test="startDate != null">
  12. 12.             AND start_date >= #{startDate}
  13. 13.         </if>
  14. 14.         <if test="endDate != null">
  15. 15.             AND end_date <= #{endDate}
  16. 16.         </if>
  17. 17.     </where>

18. </select>



<where>元素只有在其内部标签有返回内容时才会在动态语句上插入 WHERE 条件语句。并且,如果WHERE 子句以 AND 或者 OR 打头,则打头的 AND 或 OR 将会被移除。

如果 tutor_id 参数值为 null,并且 courseName 参数值不为 null,则<where>标签会将 AND name like #{courseName} 中的 AND 移除掉,生成的 SQL WHERE 子句为:where name like #{courseName}。 

 

 

trim 

<trim>元素和<where>元素类似,但是<trim>提供了在添加前缀/后缀 或者 移除前缀/后缀方面提供更大的灵活 性。 

 

  1. <select id="searchCourses" parameterType="hashmap"  resultMap="CourseResult">
  2.  SELECT * FROM COURSES
  3. <trim prefix="WHERE" prefixOverrides="AND | OR">
     
    <if test=" tutorId != null ">
  4. TUTOR_ID= #{tutorId}
  5. </if>
  6. <if test="courseName != null">
  7. AND name like #{courseName}
  8. </if>
  9. </trim>

10. </select>

这里如果任意一个<if>条件为 true,<trim>元素会插入 WHERE,并且移除紧跟 WHERE 后面的 AND 或OR 

 

foreach 

  1. <select id="searchCoursesByTutors" parameterType="map"
  2. resultMap="CourseResult">
  3. SELECT * FROM COURSES
  4. <if test="tutorIds != null">
  5. <where>
  6. <foreach item="tutorId" collection="tutorIds">
  7. OR tutor_id=#{tutorId}
  8. </foreach>
  9. </where>

10. </if>

11. </select>

 

  1. <select id="searchCoursesByTutors" parameterType="map"
  2. resultMap="CourseResult">
  3.     SELECT * FROM COURSES
  4.     <if test="tutorIds != null">
  5. <where>
  6.         tutor_id IN
  7.             <foreach item="tutorId" collection="tutorIds"
  8.             open="(" separator="," close=")">
  9.             #{tutorId}
  10. 10.             </foreach>
  11. 11.         </where>
  12. 12.     </if>

13. </select>

 

set 

<set>元素和<where>元素类似,如果其内部条件判断有任何内容返回时,他会插入 SET SQL 片段。 

  1. <update id="updateStudent" parameterType="Student">
  2.          update students
  3.          <set>
  4.                   <if test="name != null">name=#{name},</if>
  5.                   <if test="email != null">email=#{email},</if>
  6.                   <if test="phone != null">phone=#{phone},</if>
  7.          </set>
  8.          where stud_id=#{id}
  9. </update>

 

这里,如果<if>条件返回了任何文本内容,<set>将会插入set关键字和其文本内容,并且会剔除将末尾的 “,”。 在上述的例子中,如果 phone!=null,<set>将会让会移除 phone=#{phone}后的逗号“,”,

生成 set phone=#{phone} 。 

 

 

注解SQL

  • Insert
  1. public interface StudentMapper
  2. {
  3.     @Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)
  4.             VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})")
  5.     int insertStudent(Student student);
  6. }

 

使用了@Insert 注解的 insertMethod()方法将返回 insert 语句执行后影响的行数。 

[自动生成主键] 

MySQL

  1. @Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
  2.         VALUES(#{name},#{email},#{address.addrId},#{phone})")
  3. @Options(useGeneratedKeys = true, keyProperty = "studId")
  4. int insertStudent(Student student);

Oracle

  1. @Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)
  2. VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})")
  3. @SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",
  4. keyProperty="studId", resultType=int.class, before=true)
  5. int insertStudent(Student student);

 

如果你使用序列作为触发器来设置主键值,我们可以在 INSERT 语句执行后,从 sequence_name.currval 获取数据 库产生的主键值。 

  1. @Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
  2. VALUES(#{name},#{email},#{address.addrId},#{phone})")
  3. @SelectKey(statement="SELECT STUD_ID_SEQ.CURRVAL FROM DUAL",
  4. keyProperty="studId", resultType=int.class, before=false)
  5. int insertStudent(Student student);

 

 @font-face { font-family: "Courier New"; }@font-face { font-family: "宋体"; }@font-face { font-family: "Cambria Math"; }@font-face { font-family: "@宋体"; }@font-face { font-family: "Calibri"; }@font-face { font-family: "Menlo"; }p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0cm 0cm 0.0001pt; text-align: justify; font-size: 12pt; font-family: Calibri; }h1 { margin: 17pt 0cm 16.5pt; text-align: justify; line-height: 240%; page-break-after: avoid; font-size: 22pt; font-family: Calibri; }pre { margin: 0cm 0cm 0.0001pt; font-size: 10pt; font-family: "Courier New"; }span.HTML { font-family: "Courier New"; }.MsoChpDefault { font-family: Calibri; }div.WordSection1 { }

Dao

StudentDao

package org.zln.dao;

import java.io.IOException;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.zln.domain.Student;
import org.zln.mapper.StudentMapper;
import org.zln.utils.DBAccess;

/**
 * Created by sherry on 16/7/15.
 */
public class StudentDao {

    public List<Student> findAllStudents() throws IOException {
        SqlSession sqlSession = DBAccess.getSqlSession();
        try{
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            return studentMapper.findAllStudents();
        } finally{
            sqlSession.close();
        }
    }
    public Student findStudentById(Integer studId) throws IOException {
        SqlSession sqlSession = DBAccess.getSqlSession();
        try {
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            return studentMapper.findStudentById(studId);
        } finally {
            sqlSession.close();
        }
    }
    public void createStudent(Student student) throws IOException {
        SqlSession sqlSession = DBAccess.getSqlSession();
        try {
            StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
            studentMapper.insertStudent(student);
            sqlSession.commit();
        }finally{
            sqlSession.close();
        }
    }




}

 

Mapper接口

StudentMapper

package org.zln.mapper;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.zln.domain.Student;

import java.util.List;

/**
 * Created by sherry on 16/7/15.
 * Student
Mapper接口
 */
public interface StudentMapper {

    List<Student> findAllStudents();

    @Select("SELECT stud_id AS studId, name, email, dob FROM Student WHERE STUD_ID=#{Id}")
    Student findStudentById(Integer id);

    @Insert("INSERT INTO Student(stud_id,name,email,dob) VALUES(#{studId},#{name},#{email},#{dob})")
    void insertStudent(Student student);

}

映射文件