SQL映射文件详解

1.1SQL映射文件

SQL映射是MyBatis框架最具特色的部分,功能强大且使用简单。MyBatis框架的主要思想是讲SQL语句从程序代码中分离出来,对JDBC访问数据库的代码进行封装,从程序中消除了所有的SQL参数设置及处理结果集的JDBC代码,从而大幅减少数据访问层的编码量。

SQL映射文件中的几个顶级元素介绍如下:

①mapper:SQL映射文件的根元素。只有一个属性namespace,用于区分不同的mapper,必须全局唯一。

②cache:为给定命名空间配置缓存

③cache-ref:引用其他命名空间中的缓存配置。

④resultMap:用来描述查询结果集中的字段和java实体类属性的对应关系

⑤sql:定义可重用的SQL语句快,可以在其他语句映射中引用,提高编写和维护SQL语句的效率

⑥insert:映射inset语句

⑦update:映射update语句

⑧delete:映射delete语句

⑨select:映射select语句

SQL映射文件的开发需要注意以下规则:

①习惯上,SQL映射文件与该Mapper接口同名(实体类名+Mapper),并放置在同一包路径下。

②以要映射的Mapper接口的完全限定名(即包含包名的完整名称)作为namespace属性的值。

③接口中的方法名与映射文件中SQL语句映射的ID一一对应。MyBatis框架通过namespace+ID确定和接口方法绑定的SQL语句。

④在不同的SQL映射文件中,子元素的ID可以相同。

1.2MyBatis框架的条件查询

1.2.1实现单一条件查询

(1)在接口中添加查询方法:

/**
 * 根据用户的真实姓名模糊匹配查询用户,参数realName为需要传递给SQL语句的查询条件
 */
public List<SysUser> getUserByRealName(String realName);

(2)在xml文件中添加SQL语句映射:

<select id="getUsersByRealName" resultType="sysuser" parameterType="string">
    select * from t_sys_user where realName like concat('%',#{param},'%')
</select>

(3)在测试类中添加测试方法: 

......//省略创建SqlSession的代码
List<SysUser> userList = sqlSession.getMapper(接口类名.class).getUserByRealName("李");
......//省略输出查询结果的代码

1.2.2实现多条件查询

有三种实现方法

1.将查询条件封装成java对象作为入参
2.将查询条件封装成Map对象作为入参
3.使用@Param注解时间多参数入参

在映射的SQL语句中使用默认命名表意不直观,且调整顺序容易出错,所以推荐使用@Param注解为参数命名。例如@Param(“realName”)String realName,相当于改参数的可以命名为realName,便于在映射的SQL中使用。

1.2.3MyBatis框架的结果映射

使用mybatis,有两个属性标签<resultType><resultMap>可以提供结果映射

虽然resultType 属性在大部分情况下都够用,但是在一些特殊情况下无能为力,比如属性名和列名不一致,为一些连接的复杂语句编写映射代码。

遇到这些情况,我们要使用<resultMap>标签,一份 <resultMap> 能够代替实现同等功能的数千行代码。

1.2.3.1使用resultMap元素自定义结果映射

MyBatis框架使用resultMap元素来自定义结果映射。

resultMap 元素是 MyBatis 中最重要最强大的元素。
resultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

属性名和列名不一致

这是开发过程中常见的情境,JavaBean 属性使用驼峰命名,数据库列名单词之间加入下划线。

public class User {
  private int id;
  private String username;
  private String hashedPassword;

  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 getHashedPassword() {
    return hashedPassword;
  }
  public void setHashedPassword(String hashedPassword) {
    this.hashedPassword = hashedPassword;
  }
}
<select id="selectUsers" resultType="User">
  select
    user_id,user_name,hashed_password
  from some_table
  where id = #{id}
</select>

为了解决上述问题,我们只需要在 <resultMap>中做一下简单的配置,然后在引用它的语句中设置 <resultMap> 属性就行了 

<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap> 
<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>

注意:这里去掉了<reslutType>属性,用<resultMap>代替,二者只能选择其中的一个。 

 高级结果映射

MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。

我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。

如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,可惜没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。

一对一映射

比如,我们如何映射下面这个语句?

<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
  select
       B.id as blog_id,
       B.title as blog_title,
       B.author_id as blog_author_id,
       A.id as author_id,
       A.username as author_username,
       A.password as author_password,
       A.email as author_email,
       A.bio as author_bio,
       A.favourite_section as author_favourite_section
  from Blog B
  left outer join Author A on B.author_id = A.id
  where B.id = #{id}
</select>

这是典型的一对一的关联关系情况,我们通过<association>配置就可以解决这个问题。

<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>
</resultMap>
接下来,我们一步一步来看这些元素的意义。 
reslutMap 的属性

id:当前命名空间中的一个唯一标识,用于标识一个结果映射。
type:类的完全限定名, 或者一个类型别名。

id和result

 id 和 result 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。

这两者之间的唯一不同是,id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

两者的一些属性:

property:映射到列结果的字段或属性。
column:数据库中的列名,或者是列的别名。
javaType:一个 Java 类的全限定名,或一个类型别名。通常不会配置,mybatis 能够根据参数信息自动识别,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
jdbcType:JDBC 类型,所支持的 JDBC 类型参见这个表格之后的“支持的 JDBC 类型”。

多对多映射

首先来看对应的 SQL 语句:

<select id="selectBlog" resultMap="blogResult">
  select
  B.id as blog_id,
  B.title as blog_title,
  B.author_id as blog_author_id,
  P.id as post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.id = P.blog_id
  where B.id = #{id}
</select>
<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <result property="body" column="post_body"/>
  </collection>
</resultMap>

javaBean 中我们这样表示集合:

private List<Post> posts;

 

大部分都和我们上面学习过的关联元素非常相似,这里只是新增了一个 ofType属性。

这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。 所以你可以按照下面这样来阅读映射:

<collection property="posts" javaType="ArrayList" ofType="Post"/>

读作: “posts 是一个存储 Post 的 ArrayList 集合”。
在一般情况下,MyBatis 可以推断 javaType 属性,因此并不需要填写。所以很多时候你可以简略成:

<collection property="posts" ofType="Post"/>

配合少许的实践,你会很快了解全部的用法。 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值