Mybatis使用之映射篇

最通常的情况下数据表字段和我们的pojo应该是一一对应得关系,即字段和类属性一对一。如果对象的属性也是也是一个对象,即涉及两个表的关联,此时应该如何进行映射处理呢? 目前有两张表如下:

对应得pojo类:


public class Book {
    private int id;
    private String name;
    private int price;
    private Author author;
    //... getter and setter
}

public class Author {
    private int id;
    private String name;
    private int age;
    private List<Book> bookList;
    //... getter and setter
}

由上述情况,Mybatis引入association关联

当我们查询一个book类,且需要将author属性获取出来,我们需要用到association。

association的三种用法

  1. 第一种用法:association中使用select

定义AuthorDao.java,如下:

public interface AuthorDao {
    Author queryAuthorById(int authorId);
}

在AuthorDao.xml中实现该方法:

<select id="queryAuthorById" parameterType="int" resultType="Author">
        SELECT a.*, b.id AS 'book_id', b.name AS 'book_name', b.price AS 'book_price'
        FROM author a, book b
        WHERE a.id = b.author_id
        AND a.id = #{authorId}
 </select>

然后在BookDao.xml中是如何引用该方法的:

<resultMap type="Book" id="bookMap">
    <result property="name"
         column="name"/>
    <result property="price"
         column="price"/>
   <association property="author"
         column="author_id"
         select="com.zhu.ssm.dao.
         AuthorDao.queryAuthorById">
   </association>
</resultMap>

在这里直接通过select引用AuthorDao的queryAuthorById方法。个人感觉这种方法比较麻烦,因为还要在AuthorDao里定义queryAuthorById方法并且实现再引用才有用,不过这种方法思路清晰,易于理解。

  1. 第二种方法,嵌套resultMap
<resultMap type="Author" id="authorMap">
      <id property="id"
            column="authorId"/>
      <result property="name"
                   column="authorName"/>
      <result property="age"
                   column="authorAge"/>
</resultMap>


<resultMap type="Book" id="bookMap">
     <id property="id" column="id"/>
     <result property="name"
                  column="name"/>
     <result property="price"
                  column="price"/>
     <association property="author"
                             resultMap="authorMap">
     </association>
</resultMap>

第二种方法就是在BookDao.xml中先定义一个Author的resultMap,然后在Book的resultMap的association标签中通过resultMap="authorMap"引用。这种方法相比于第一种方法较为简单。

  1. 第三种方法:嵌套resultMap简化版
<resultMap type="Book" id="bookMap">
   <result property="name"
                  column="name"/>
   <result property="price"
                  column="price"/>
   <association
          property="author"
          javaType="Author">
     <!--注:此处column应为book中外键列名-->
      <id property="id"
                column="author_id"/>
      <result property="name"
                       column="authorName"/>
      <result property="age"
                       column="authorAge"/>
    </association>
</resultMap>
<!--嵌套查询,结果映射只能使用resultMap-->
    <select id="findBookById" parameterType="long" resultMap="bookResultMap">
        SELECT
            b.*,
            a.name AS 'authorName',
            a.age  AS 'authorAge'
        FROM book b, author a
        WHERE b.author_id = a.id
        AND b.id = #{id}
    </select>

这种方法就把Author的resultMap定义在了association 标签里面,通过javaType来指定是哪个类的resultMap,个人认为这种方法最简单,缺点就是authorMap不能复用。具体用哪种方法,视情况而定。


collection的三种用法:

pojo如下:

User实体类

public class User{
  private Integer userId;
    private String userName;
    private Integer age;
    private List<MobilePhone> mobilePhone;//土豪,多个手机,1对多
}

手机类

public class MobilePhone {
    private Integer mobilePhoneId;
    private String brand;//品牌
    private double price;//价格
    private User user;//主人
}

dao层

public interface UserDao {
    /**
     * 通过userId查询user信息
     * @param userId
     * @return
     */
    User queryById(int userId);
}

UserDao.xml中的select查询语句

<select id="queryById" parameterType="int" resultMap="userMap">
        SELECT u.user_name,u.age,
                       m.brand,m.price
        FROM tb_user u,tb_mobile_phone m
        WHERE m.user_id=u.user_id
        AND
        u.user_id=#{userId}
</select>

数据库中,tb_mobile_phone中user_id作为外键。那么下面来看resultMap如何定义:

  1. 用select,和association中使用select类似:

先定义 MobilePhoneDao.java

public interface MobilePhoneDao {
    List<MobilePhone> queryMbByUserId(int userId);
}

然后实现该方法 MobilePhoneDao.xml

<resultMap type="MobilePhone"
                    id="mobilePhoneMap">
     <id property="mobilePhoneId"
           column="user_id"/>
     <result property="brand"
                  column="brand"/>
     <result property="price"
                  column="price"/>
     <association property="user"
               column="user_id" select=
      "com.zhu.ssm.dao.UserDao.queryById">
     </association>
</resultMap>

<select id="queryMbByUserId" parameterType="int" resultMap="mobilePhoneMap">
        SELECT brand,price
        FROM tb_mobile_phone
        WHERE user_id=#{userId}
</select>

做好以上准备工作,那就可以在UserDao.xml中引用了

<resultMap type="User" id="userMap">
        <id property="userId" column="user_id"/>
        <result property="userName"
                     column="user_name"/>
    <result property="age"
                     column="age"/>
    <collection property="mobilePhone"
                column="user_id"
                select="com.zhu.ssm.dao
       .MobilePhoneDao.queryMbByUserId">
        </collection>
</resultMap>

这种方法和association的第一种用法几乎是一样的不同之处就是mobilePhMap中用到了association ,queryMbByUserId中要使用mobilePhoneMap,而不能直接使用resultType。

  1. 第二种方法:嵌套resultMap
<resultMap type="MobilePhone" id="mobilephoneMap">
         <id column="mobile_phone_id" property="mobilePhoneId"/>
         <result column="brand" property="brand" />
         <result column="price" property="price" /></resultMap>

<resultMap type="User" id="userMap">
        <result property="userName" column="user_name"/>
        <result property="age" column="age"/>
        <collection property="mobilePhone" resultMap="mobilephoneMap" >
        </collection>
</resultMap>

定义好这两个resultMap,再引用UserMap就行了。

<resultMap type="User" id="userMap">
        <result property="userName" column="user_name"/>
     <result property="age" column="age"/>
     <collection property="mobilePhone"
                  column="user_id"
                 ofType="MobilePhone">
      <id column="mobile_phone_id" property="mobilePhoneId" />
      <result column="brand"
                       property="brand" />
      <result column="price"
                      property="price" />
 </collection>
</resultMap>

这种方法需要注意,一定要有ofType,collection 装的元素类型是啥ofType的值就是啥,这个一定不能少。 注意: 所有resultMap中的type、select 标签中的resultType以及association中的javaType,collection中的ofType,这里只写了类名,是因为在mybatis-config.xml中配置了typeAliases,否则就要写该类的全类名。配置如下:

<typeAliases>
<packagename="com.zhu.smm.entity"/>
</typeAliases>

总结:

1、association表示的是has one的关系,一对一时使用。book has one author,所以在book的resultMap中接收author时应该用association;

2、collection表示的是has many的关系,一对多时使用。user has many mobilePhone,所以在user的resultMap中接收mobilePhone时应该用collection。

3、都有三种用法,且非常类似,resultMap要复用建议第二种方法,不需要复用建议第三种方法。

4、特别注意表中主键字段要有所区分,不能都写成id,要写成user_id、card_id,反正要有所区分,不然查询的时候会查不到完整的数据。

转载于:https://my.oschina.net/u/4086883/blog/3030149

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值