文章出處

從這一篇博文開始,將總結一下mybatis中的幾個高級映射,即一對一、一對多、多對多查詢,這篇先總結一下mybatis中的一對一查詢。 
  為了模擬這些需求,事先要建立幾個表,不同的表之間將對應上面提到的不同的映射,為此,我建立4個表,如下:

 

DROP TABLE IF EXISTS `items`;
DROP TABLE IF EXISTS `orders`;
DROP TABLE IF EXISTS `user`;
DROP TABLE IF EXISTS `orderdetail`;

/*items是商品表*/
CREATE TABLE `items` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NOT NULL COMMENT '商品名稱',
  `price` FLOAT(10,1) NOT NULL COMMENT '商品定價',
  `detail` TEXT COMMENT '商品描述',
  `pic` VARCHAR(64) DEFAULT NULL COMMENT '商品圖片',
  `createtime` DATETIME NOT NULL COMMENT '生產日期',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*user是用戶表*/
CREATE TABLE `user` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(32) NOT NULL COMMENT '用戶名稱',
  `birthday` DATE DEFAULT NULL COMMENT '生日',
  `sex` CHAR(1) DEFAULT NULL COMMENT '性別',
  `address` VARCHAR(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

/*orders是訂單表*/
CREATE TABLE `orders` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `user_id` INT(11) NOT NULL COMMENT '下單用戶id',
  `number` VARCHAR(32) NOT NULL COMMENT '訂單號',
  `createtime` DATETIME NOT NULL COMMENT '創建訂單時間',
  `note` VARCHAR(100) DEFAULT NULL COMMENT '備注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*orderdetail是訂單明細表*/
DROP TABLE IF EXISTS orderdetail;
CREATE TABLE `orderdetail` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `orders_id` INT(11) NOT NULL COMMENT '訂單id',
  `items_id` INT(11) NOT NULL COMMENT '商品id',
  `items_num` INT(11) DEFAULT NULL COMMENT '商品購買數量',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`orders_id`),
  KEY `FK_orderdetail_2` (`items_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

 

每個表對應的po就不寫了。從上面的表中,可以分析出下面的一些關系: 
表的關系 
  這一節主要總結mybatis中一對一的映射,所以我選擇左邊orders和user之間的一對一關系來總結,主要是查詢訂單信息,關聯查詢創建訂單的用戶信息。 
  我們知道,查詢結果可以使用resultType,也可以使用resultMap,在這里我兩種方法都使用一下,然后對比一下各個方法的特點。

 

1. resultType方法

1.1 sql查詢語句

  寫查詢語句的時候首先得確定查詢的主表,這里是訂單表,然后關聯表是用戶表。由于orders表中有一個外鍵(user_id),通過此外鍵關聯查詢用戶表只能查詢出一條記錄,所以使用內連接。查詢的sql如下:

 

SELECT 
  orders.*,
  USER.username,
  USER.sex,
  USER.address 
FROM
  orders,
  USER 
WHERE orders.user_id = user.id

 

  有了sql,接下來就是創建pojo了

1.2 創建pojo

  使用resultType的話,有個前提就是查詢結果要想映射到pojo中去,pojo中必須包括所有查詢出的列名才行。這里不僅查詢出order表中的所有字段,而且還查詢出了用戶表中的部分字段,所以我們要自己新建一個pojo來包含所有的這些查詢出來的字段才行。 
  創建pojo的原則是繼承包括查詢字段較多的po類。

 

//通過此類映射訂單和用戶查詢的結果,讓此類繼承包括字段較多的po類
public class OrdersCustom extends Orders {

    //繼承了Orders,已經有了Orders的所有屬性了
    //下面添加用戶屬性
    private String username;
    private String sex;
    private String address;

    //省略get和set方法
}

 

  接下來就可以寫mapper.xml映射文件了。

1.3 UserMapperOrders.xml配置文件

<mapper namespace="mybatis.mapper.UserMapperOrders">

    <select id="findOrdersUser" resultType="mybatis.po.OrdersCustom">
        SELECT 
          orders.*,
          user.`username`,
          user.`sex`,
          user.`address` 
        FROM
          orders,
          USER 
        WHERE orders.`user_id` = user.`id` 
    </select>
</mapper>

1.4 UserMapperOrders.java接口

public interface UserMapperOrders {

    //查詢訂單,關聯查詢用戶信息
    public List<OrdersCustom> findOrdersUser() throws Exception;
}

注意接口和映射文件要放在同一個目錄下,因為SqlMapConfig.xml文件中配置的是批量加載mapper,這里可以參考我的這篇博文:mybatis第5篇。 
  到這里就完成了使用resultType方法來實現一對一查詢了,下面測試一下:

 

@Test
    public void testUserMapperOrders() throws Exception {
        //獲取sqlSessionFactory的代碼省略了
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapperOrders userMapperOrders = sqlSession.getMapper(UserMapperOrders.class);
        List<OrdersCustom> list = userMapperOrders.findOrdersUser();
        System.out.println(list);
    }

 

從上面可以看出,使用resultType的流程很簡單,還是和之前的一樣,關鍵還是在sql語句上,這也是mybatis的強大之處,自己寫sql語句,想怎么查就怎么查。下面再總結一下使用resultMap方法來實現一對一查詢。

2.resultMap方法

還是上面那個sql,使用resultMap方法的思路如下:使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在Orders類中添加User屬性,將關聯查詢出來的用戶信息映射到Orders對象中的User屬性中。所以現在Orders類中添加一項User屬性,我就不寫具體的代碼了。 
  學過hibernate就會感覺這里和Hibernate有點像,如果用Hibernate,這里也是在Orders類中添加一個User屬性,將查詢Orders關聯出的User放到User屬性中。

2.1 定義resultMap

<resultMap type="mybatis.po.Orders" id="OrdersUserResultMap">
    <!-- 配置映射訂單信息 -->
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property="note"/>

    <!-- 配置映射的關聯的用戶信息 -->
    <!-- association用于映射關聯查詢單個對象的信息
        property:要將關聯查詢的用戶信息映射到Orders中的哪個屬性
        javaType:該屬性的類型
     -->
    <association property="user" javaType="mybatis.po.User">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
    </association>
</resultMap>

 這里主要用到了<association>標簽,值用來映射關聯查詢單個對象的信息,關于resultMap的一些標簽屬性我在前面的博客中已經解釋過了,這里不再贅述。

2.2 UserMapperOrders.xml配置文件

<select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
    SELECT 
      orders.*,
      user.`username`,
      user.`sex`,
      user.`address` 
    FROM
      orders,
      USER 
    WHERE orders.`user_id` = user.`id` 
</select>

 配置和上面resultType一樣的,唯一區別在于id和resultMap,注意一下就行了。

2.3 UserMapperOrders.java接口

public interface UserMapperOrders {

    //查詢訂單,關聯查詢用戶信息,使用resultMap
    public List<OrdersCustom> findOrdersUserResultMap() throws Exception;

}

也很簡單,不再多說了。下面測試一下:

@Test
    public void testUserMapperOrdersResultMap() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapperOrders userMapperOrders = sqlSession.getMapper(UserMapperOrders.class);
        List<OrdersCustom> list = userMapperOrders.findOrdersUserResultMap();
        System.out.println(list);
    }

到這里,resultMap方法完成的一對一查詢映射就總結完了,從這里可以看出,resultMap方法和hibernate中其實是有點像的。下面再總結一下resultType和resultMap的區別:

 

3. resultType和resultMap

實現一對一查詢:

  1. resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。如果沒有查詢結果的特殊要求建議使用resultType。
  2. resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。
  3. resultMap可以實現延遲加載,resultType無法實現延遲加載。

每篇我都有寫好存在百度云的 有需要給我留言 

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()