MyBatis教程--XML映射器(四)

最全最详细的介绍:Mybatis官网

1 select

查询语句是 MyBatis 中最常用的元素之一——光能把数据存到数据库中价值并不大,还要能重新取出来才有用,多数应用也都是查询比修改要频繁。 MyBatis 的基本原则之一是:在每个插入、更新或删除操作之间,通常会执行多个查询操作。因此,MyBatis 在查询和结果映射做了相当多的改进。一个简单查询的 select 元素是非常简单的。比如:

<select id="selectPerson" parameterType="int" resultType="hashmap">
  SELECT * FROM PERSON WHERE ID = #{id}
</select>

这个语句名为 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。
select 元素属性:

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

2 insert, update 和 delete

数据变更语句 insert,update 和 delete 的实现非常接近:

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

在插入语句里面有一些额外的属性和子元素用来处理主键的生成,并且提供了多种生成方式:

  1. 如果数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为主键就可以了
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
  insert into t_user(username,password)
  values (#{username},#{password})
</insert>
  1. 对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis还可以通过selectKey来实现
<insert id="insertAuthor">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select s_user.next form dual
  </selectKey>
  insert into t_user
    (id, username, password)
  values
    (#{id}, #{username}, #{password})
</insert>

在上面的示例中,首先会运行 selectKey 元素中的语句,并设置 t_user的 id,然后才会调用插入语句。这样就实现了数据库自动生成主键类似的行为,同时保持了 Java 代码的简洁。
selectKey 元素描述如下:

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

3 sql

这个元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include 元素中定义不同的参数值。

    <sql id="usertable">
        ${tableName}
    </sql>

    <sql id="userinclude">
        from
        <include refid="${include_target}"/>
    </sql>

    <select id="queryUserById" parameterType="int" resultType="User">
        select
        id, password, username
        <include refid="userinclude">
            <property name="include_target" value="usertable"/>
            <property name="tableName" value="t_user"/>
        </include>
        where id = #{id}
    </select>

以上xml会被解析为select id, password, username from t_user where id = ?

3.1 参数

sql的参数可以指定java类型,数据库类型和类型处理器

#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}

对于数值类型,还可以设置 numericScale 指定小数点后保留的位数

#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}

mode 属性允许你指定 IN,OUT 或 INOUT 参数。如果参数的 mode 为 OUT 或 INOUT,将会修改参数对象的属性值,以便作为输出参数返回。 如果 mode 为 OUT(或 INOUT),而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),你必须指定一个 resultMap 引用来将结果集 ResultMap 映射到参数的类型上。要注意这里的 javaType 属性是可选的,如果留空并且 jdbcType 是 CURSOR,它会被自动地被设为 ResultMap。

#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}

3.2 字符串替换(${})

当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用

@Select("select * from t_user where id = #{id}")
User findById(@Param("id") long id);

@Select("select * from t_user where username= #{name}")
User findByName(@Param("name") String name);

可以写成
@Select("select * from t_user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

4 结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
User.java

package com.jing.model;

public class User {
    private int id;
    private String userName;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

t_user表

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `pwd` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

我们可以看出t_user表的name和pwd跟User对象userName和password是不对应的这样Mybatis无法正常对User对象进行复制,我们需要一个映射关系

<select id="queryAllUser" resultType="User">
    select * from t_user
</select>
转换成
<resultMap id="userResultMap" type="User">
    <id property="id" column="id" />
    <result property="userName" column="name"/>
    <result property="password" column="pwd"/>
</resultMap>

<select id="queryAllUser" resultMap="userResultMap">
    select * from t_user
</select>

5 高级结果映射

高级结果映射过于复杂可以参考Mybatis官网

<!-- 非常复杂的结果映射 -->
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="username" column="author_username"/>
    <result property="password" column="author_password"/>
    <result property="email" column="author_email"/>
    <result property="bio" column="author_bio"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>

上一章:MyBatis教程–作用域(Scope)和生命周期(三)
下一章:MyBatis教程–分页(五)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值