從這一篇博文開始,將總結一下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
實現一對一查詢:
- resultType:使用resultType實現較為簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。如果沒有查詢結果的特殊要求建議使用resultType。
- resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。
- resultMap可以實現延遲加載,resultType無法實現延遲加載。
每篇我都有寫好存在百度云的 有需要給我留言
文章列表