Mybatis中的关联映射和查询

一、商品订单数据模型
1、数据表
这里定义了四个表,分别表示用户,商品,订单,和订单详情。
用户表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

表中的数据如下图:



商品表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
表中的数据如下图:

订单表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
在订单表中有一个外键user_id,和用户表user中的id相关联。
表中的数据如下图:


订单详情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=6 DEFAULT CHARSET=utf8
在订单详情表中有两个外键:orders_id和订单表orders中的id相关联;items_id和商品表items中的id相关联。
表中的数据如下图:

综合以上四张表,结合里面已有的数据,最终整合得到如下信息:
张三有编号为1000010和1000011两个订单。其中1000010订单包含1个台式机和3个笔记本;1000011订单包含4个IPAD和3个笔记本。
而李四有一个编号为1000012的订单,包含2个IPAD。
信息如下图:


2、表与表之间的关系
先分析明确有外键关联的数据表。
user和orders:
user---->orders:一个用户可以创建多个订单,一对多。
orders--->user:一个订单只能属于一个用户,一对一。

orders和orderdetail:
orders--->orderdetail:一个订单可以包括多个订单明细。因为一个订单可以购买多个商品,每个商品的购买信息都在orderdetail有一行记录。一对多关系。
orderdetail--->orders:一个订单明细只能属于一个订单,一对一。

orderdetail和items:
orderdetail--->items:一个订单明细只对应一个商品信息,一对一。
items---> orderdetail:一个商品可以属于多个订单明细(在不同的订单中) ,一对多。

再分析没有明确关系的表之间是否有业务关系:
orders和items:
通过订单明细表orderdetail,orders和items可以建立关系。
orders--->items一个订单可以包含多个商品,一对多。
items--->orders一个商品可以属于多个订单,一对多。
订单表和商品表是多对多关系。


二、建立数据表对应的POJO类
1、user.java
package com.kang.pojo;


import java.io.Serializable;
import java.util.Date;
import java.util.List;


public class user implements Serializable {
	
	//属性名和数据库表的字段对应
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址
	
	//用户创建的订单列表
	private List<Orders> ordersList;
	
	
	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 getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public List<Orders> getOrdersList() {
		return ordersList;
	}
	public void setOrdersList(List<Orders> ordersList) {
		this.ordersList = ordersList;
	}
	@Override
	public String toString() {
		return "user [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
				+ address + ", ordersList=" + ordersList + "]";
	}




}




2、Items.java
package com.kang.pojo;


import java.util.Date;


public class Items {
    private Integer id;
    private String name;
    private Float price;
    private String pic;
    private Date createtime;
    private String detail;
    
    public Integer getId() {
        return id;
    }


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


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }


    public Float getPrice() {
        return price;
    }


    public void setPrice(Float price) {
        this.price = price;
    }


    public String getPic() {
        return pic;
    }


    public void setPic(String pic) {
        this.pic = pic == null ? null : pic.trim();
    }


    public Date getCreatetime() {
        return createtime;
    }


    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }


    public String getDetail() {
        return detail;
    }


    public void setDetail(String detail) {
        this.detail = detail == null ? null : detail.trim();
    }


	@Override
	public String toString() {
		return "Items [id=" + id + ", name=" + name + ", price=" + price
				+ ", pic=" + pic + ", createtime=" + createtime + ", detail="
				+ detail + "]";
	}
    
}




3、Orders.java
package com.kang.pojo;


import java.util.Date;
import java.util.List;


public class Orders {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    //用户信息
    private user user;
    //订单明细
    private List<Orderdetail> orderdetails;


    public Integer getId() {
        return id;
    }


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


    public Integer getuserId() {
        return userId;
    }


    public void setuserId(Integer userId) {
        this.userId = userId;
    }


    public String getNumber() {
        return number;
    }


    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }


    public Date getCreatetime() {
        return createtime;
    }


    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }


    public String getNote() {
        return note;
    }


    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }


	public user getuser() {
		return user;
	}


	public void setuser(user user) {
		this.user = user;
	}


	public List<Orderdetail> getOrderdetails() {
		return orderdetails;
	}


	public void setOrderdetails(List<Orderdetail> orderdetails) {
		this.orderdetails = orderdetails;
	}


	@Override
	public String toString() {
		return "Orders [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
				+ ", note=" + note + ", user=" + user + ", orderdetails=" + orderdetails + "]";
	}


    
}




4、Orderdetail.java
package com.kang.pojo;


public class Orderdetail {
    private Integer id;
    private Integer ordersId;
    private Integer itemsId;
    private Integer itemsNum;
    //明细对应的商品信息
    private Items items;
    
    public Integer getId() {
        return id;
    }


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


    public Integer getOrdersId() {
        return ordersId;
    }


    public void setOrdersId(Integer ordersId) {
        this.ordersId = ordersId;
    }


    public Integer getItemsId() {
        return itemsId;
    }


    public void setItemsId(Integer itemsId) {
        this.itemsId = itemsId;
    }


    public Integer getItemsNum() {
        return itemsNum;
    }


    public void setItemsNum(Integer itemsNum) {
        this.itemsNum = itemsNum;
    }


	public Items getItems() {
		return items;
	}


	public void setItems(Items items) {
		this.items = items;
	}


	@Override
	public String toString() {
		return "Orderdetail [id=" + id + ", ordersId=" + ordersId
				+ ", itemsId=" + itemsId + ", itemsNum=" + itemsNum + "]";
	}
    
}



二、一对一查询
这里对Mybatis的基础配置信息不再列出,只分析对应的映射文件的内容。
业务需求:查询出订单信息,并且关联查询出创建订单的用户信息。
1、构想查询的SQL语句
查询涉及的数据表:orders和user。
查询的结果信息:orders表的全部字段信息和user的三个信息。
如何关联:通过外键orders.user_id = user.id。
SQL查询语句如下:
SELECT
orders.*,
user.username,
user.sex,
user.address
FROM
orders,
user
WHERE orders.user_id = user.id

2、实现方案
第一种:使用POJO扩展类来映射,从而避免使用resultMap。
首先根据查询结果的形式定义POJO类:这个类继承自Orders类。
package com.kang.pojo;
//通过此类映射订单和用户查询的结果,让此类继承包括字段较多的pojo类。
public class OrdersCustom extends Orders{
	
	//添加用户属性
	/*user.username,
	  user.sex,
	  user.address */
	
	private String username;
	private String sex;
	private String address;
	public String getusername() {
		return username;
	}
	public void setusername(String username) {
		this.username = username;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "OrdersCustom [username=" + username + ", sex=" + sex + ", address=" + address + "]";
	}


}

然后再映射XML文件中用resultType来指定。
<!-- 查询订单关联查询用户信息,使用 resultType -->
	<select id="findOrdersuser" resultType="com.kang.pojo.OrdersCustom">
		SELECT
		orders.*,
		user.username,
		user.sex,
		user.address
		FROM
		orders,
		user
		WHERE orders.user_id
		= user.id
	</select>

之后在接口类中定义相关的方法
public interface OrdersMapperCustom {
	//查询订单关联查询用户信息
	public List<OrdersCustom> findOrdersuser()throws Exception;
}

最后进行测试
public class OrderTest {
	// 会话工厂
	private SqlSessionFactory sqlSessionFactory;
	@Before
	public void createSqlSessionFactory() throws IOException {
		// 配置文件SqlMapConfig.xml在类路径下
		String resource = "SqlMapConfig.xml";
		// 得到配置文件流
		InputStream inputStream = Resources.getResourceAsStream(resource);
		// 创建会话工厂,传入mybatis的配置文件信息
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);


	}


	@Test
	public void testFindOrdersuser() throws Exception {
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建代理对象
		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
		// 调用maper的方法
		List<OrdersCustom> list = ordersMapperCustom.findOrdersuser();


		//System.out.println(list);


		for (OrdersCustom ordersCustom : list) {
			System.out.println(ordersCustom);
		}
		sqlSession.close();
	}
}


测试结果:




第二种:不使用POJO扩展类
我们可以在Orders类中添加一个属性user,然后把查询结果映射到Orders即可。
//用户信息
private user user;
//提供get/set方法。

在XML中使用resultMap来映射。
首先定义一个resultMap片段,以供引用。
<!-- type表示订单查询关联用户的resultMap 将整个查询的结果映射到com.kang.pojo.Orders中 -->
	<resultMap type="com.kang.pojo.Orders" id="OrdersuserResultMap">
		<!-- 配置映射的订单信息 -->
		<!-- id:指定查询列中的唯一标识,也就是订单信息的中的唯一标识。如果有多个列组成唯一标识,配置多个id。 
                     column:数据库中订单信息表的唯一标识列,通常就是主键。 
                     property:订单信息表的唯一标识列所映射到Orders类中哪个属性。
                 -->
		<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中哪个属性。 
                 -->
		<association property="user" javaType="com.kang.pojo.user">
			<!-- id:关联查询用户的唯一标识。column:指定唯一标识用户信息的列,通常就是外键。 javaType:映射到user的哪个属性 -->
			<id column="user_id" property="id" />
			<result column="username" property="username" />
			<result column="sex" property="sex" />
			<result column="address" property="address" />


		</association>
	</resultMap>

然后在XML映射文件中引用该resultMap。
<!-- 查询订单关联查询用户信息,使用resultmap -->
	<select id="findOrdersuserResultMap" resultMap="OrdersuserResultMap">
		SELECT
		orders.*,
		user.username,
		user.sex,
		user.address
		FROM
		orders,
		user
		WHERE orders.user_id
		= user.id
	</select>
在接口中添加相应的方法
//查询订单关联查询用户使用resultMap
	public List<Orders> findOrdersuserResultMap()throws Exception;


在测试类中添加测试方法:
       
 @Test
	public void testFindOrdersuserResultMap() throws Exception {


		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建代理对象
		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);


		// 调用maper的方法
		List<Orders> list = ordersMapperCustom.findOrdersuserResultMap();


		//System.out.println(list);
                for (Orders orders : list) {
			System.out.println(orders);
		}


		sqlSession.close();
	}

测试结果:


详细结果:
DEBUG [main] - <==      Total: 3
Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=null]
Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=null]
Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=User [id=2, username=李四, sex=1, birthday=null, address=北京市, ordersList=null], orderdetails=null]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

3、resultType和resultMap实现一对一查询的比较
resultType:使用resultType实现较为简单,如果pojo类中没有包括查询出来的列名,需要在其中增加列名对应的属性,即可完成映射。
resultMap:需要单独定义resultMap,实现较为麻烦。如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。
如果没有查询结果的特殊要求建议使用resultType。resultMap可以实现延迟加载,resultType无法实现延迟加载。


三、实现一对多查询
业务需求:查询出所有的订单并关联查询出订单的用户和其中的订单明细。
1、构想查询的SQL语句
查询涉及的数据表:orders,user和orderdetail。
查询的结果信息:orders表的全部字段信息+user的三个信息+订单明细的四个信息。
如何关联:通过外键orders.user_id = user.id关联用户查询;通过外键orders.id=orderdetail.orders_id关联查询订单明细。
SQL查询语句如下:
SELECT
orders.*,
user.username,
user.sex,
user.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
user,
orderdetail
WHERE orders.user_id = user.id AND orders.id=orderdetail.orders_id

2、实现方案
使用resultMap来实现一对多关联。
首先需要在Orders的类中添加一个属性,来表示订单明细表。
//订单明细
private List<Orderdetail> orderdetails;
//提供get/set方法。

然后在XML中使用resultMap来映射,这里采用了继承。
<!-- 订单关联用户和订单明细的resultMap。使用extends继承,不用在中配置订单信息和用户信息的映射 -->
	<resultMap type="com.kang.pojo.Orders" id="OrdersAndOrderDetailResultMap"
		extends="OrdersuserResultMap">
		<!-- 订单信息继承而来 -->
		<!-- 用户信息继承而来 -->
		<!-- 使用extends继承,不用配置订单信息和用户信息的映射 -->
		<!-- 订单明细信息:一个订单关联查询出了多条明细,要使用collection进行一对多映射。
                     collection:对关联查询到多条记录映射到集合对象中。 
		     property:将关联查询到多条记录映射到com.kang.pojo.Orders哪个属性 。
                     ofType:指定映射到list集合属性中pojo的类型。 
                 -->
		<collection property="orderdetails" ofType="com.kang.pojo.Orderdetail">
			<!-- id:订单明细唯一标识,一般就是主键,注意这里使用了别名,结合SQL语句一看便知。
                             property:要将订单明细的唯一标识映射到com.kang.pojo.Orderdetail的哪个属性 -->
			<id column="orderdetail_id" property="id" />
			<result column="items_id" property="itemsId" />
			<result column="items_num" property="itemsNum" />
			<result column="orders_id" property="ordersId" />
		</collection>
	</resultMap>

然后在XML映射文件中引用该resultMap。
<!-- 查询订单关联查询用户及订单明细,使用resultmap -->
	<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
		SELECT
		orders.*,
		user.username,
		user.sex,
		user.address,
		orderdetail.id orderdetail_id,
		orderdetail.items_id,
		orderdetail.items_num,
		orderdetail.orders_id
		FROM
		orders,
		user,
		orderdetail
		WHERE orders.user_id = user.id AND orders.id=orderdetail.orders_id
	</select>
在接口中添加相应的方法
//查询订单(关联用户)及订单明细
	public List<Orders>  findOrdersAndOrderDetailResultMap()throws Exception;

在测试类中添加测试方法:
        @Test
	public void testFindOrdersAndOrderDetailResultMap() throws Exception {


		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建代理对象
		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);


		// 调用maper的方法
		List<Orders> list = ordersMapperCustom.findOrdersAndOrderDetailResultMap();
                for (Orders orders : list) {
			System.out.println(orders);
		}
		sqlSession.close();
	}

测试结果:


详细结果:
DEBUG [main] - <==      Total: 5
Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=[Orderdetail [id=1, ordersId=3, itemsId=1, itemsNum=1], Orderdetail [id=2, ordersId=3, itemsId=2, itemsNum=3]]]
Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=User [id=1, username=张三, sex=2, birthday=null, address=成都市, ordersList=null], orderdetails=[Orderdetail [id=3, ordersId=4, itemsId=3, itemsNum=4], Orderdetail [id=4, ordersId=4, itemsId=2, itemsNum=3]]]
Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=User [id=2, username=李四, sex=1, birthday=null, address=北京市, ordersList=null], orderdetails=[Orderdetail [id=5, ordersId=5, itemsId=3, itemsNum=2]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

3、总结
mybatis使用resultMap中collection实现一对查询,它可以把关联查询的多条记录映射到一个list集合属性中。
一对多查询也可以使用resultType实现:
我们将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。


四、实现多对多查询
业务需求:查询出所有订单,并关联查询出订单的用户,订单的明细以及订单中的商品信息。而订单和商品信息之间就是多对多关系。
1、构想查询的SQL语句
查询涉及的数据表:orders,user,orderdetail和items。
查询的结果信息:orders表的全部字段信息+user的四个信息+orderdetail的四个信息+items的三个信息。
如何关联:通过外键orders.user_id = user.id关联用户查询;通过外键orders.id=orderdetail.orders_id关联查询订单明细;通过外键orderdetail.items_id = items.id关联查询商品信息;
SQL查询语句如下:
SELECT
orders.*,
user.username,
user.sex,
user.birthday,
user.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
user,
orderdetail,
items
WHERE orders.user_id = user.id 
AND orderdetail.orders_id=orders.id 
AND orderdetail.items_id = items.id

2、实现方案
使用resultMap来实现多对多关联。
我们可以将查询结果映射到user中。
首先在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist。
然后在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials。
最后在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items。
这样我们通过user类就可得到所有我们查询到的信息。
这里不去展示具体过程,可参考上面提供的POJO类即可。
定义好POJO了类后,我们在XML中使用resultMap来映射,这里进行了collection的嵌套。
<!-- 查询用户及购买的商品 -->
	<resultMap type="com.kang.pojo.user" id="userAndItemsResultMap">
		<!-- 用户信息 -->
		<id column="user_id" property="id" />
		<result column="username" property="username" />
		<result column="sex" property="sex" />
		<result column="address" property="address" />
		<result column="birthday" property="birthday" />


		<!-- 订单信息 一个用户对应多个订单,使用collection映射 -->
		<collection property="ordersList" ofType="com.kang.pojo.Orders">
			<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" />


			<!-- 订单明细,一个订单包括多个明细 -->
			<collection property="orderdetails" ofType="com.kang.pojo.Orderdetail">
				<id column="orderdetail_id" property="id" />
				<result column="items_id" property="itemsId" />
				<result column="items_num" property="itemsNum" />
				<result column="orders_id" property="ordersId" />


				<!-- 商品信息 一个订单明细对应一个商品 -->
				<association property="items" javaType="com.kang.pojo.Items">
					<id column="items_id" property="id" />
					<result column="items_name" property="name" />
					<result column="items_detail" property="detail" />
					<result column="items_price" property="price" />
				</association>
			</collection>
		</collection>
	</resultMap>

然后在XML映射文件中引用该resultMap。
<!-- 查询用户及购买的商品信息,使用resultmap -->
	<select id="finduserAndItemsResultMap" resultMap="userAndItemsResultMap">
		SELECT
		orders.*,
		user.username,
		user.sex,
		user.birthday,
		user.address,
		orderdetail.id orderdetail_id,
		orderdetail.items_id,
		orderdetail.items_num,
		orderdetail.orders_id,
		items.name items_name,
		items.detail items_detail,
		items.price items_price
		FROM
		orders,
		user,
		orderdetail,
		items
		WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND
		orderdetail.items_id = items.id
	</select>

在接口中添加相应的方法
//查询用户购买商品信息
	public List<User>  findUserAndItemsResultMap()throws Exception;
在测试类中添加测试方法:
        @Test
	public void testFindUserAndItemsResultMap() throws Exception {


		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建代理对象
		OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);


		// 调用maper的方法
		List<User> list = ordersMapperCustom.findUserAndItemsResultMap();


		//System.out.println(list);
		for (User user : list) {
			System.out.println(user);
		}
		sqlSession.close();
	}


测试结果:




详细结果:
DEBUG [main] - <==      Total: 5
User [id=1, username=张三, sex=2, birthday=Tue Oct 27 00:00:00 CST 1998, address=成都市, ordersList=[Orders [id=3, userId=1, number=1000010, createtime=Mon Feb 27 13:22:35 CST 2017, note=尽快发货, user=null, orderdetails=[Orderdetail [id=1, ordersId=3, itemsId=1, itemsNum=1], Orderdetail [id=2, ordersId=3, itemsId=2, itemsNum=3]]], Orders [id=4, userId=1, number=1000011, createtime=Mon Feb 27 14:22:35 CST 2017, note=买来看看, user=null, orderdetails=[Orderdetail [id=3, ordersId=4, itemsId=3, itemsNum=4], Orderdetail [id=4, ordersId=4, itemsId=2, itemsNum=3]]]]]
User [id=2, username=李四, sex=1, birthday=Fri Oct 01 00:00:00 CST 1993, address=北京市, ordersList=[Orders [id=5, userId=2, number=1000012, createtime=Mon Mar 27 22:46:36 CST 2017, note=记得发中通, user=null, orderdetails=[Orderdetail [id=5, ordersId=5, itemsId=3, itemsNum=2]]]]]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5d76b067]

3、总结
一对多是多对多的特例,查询用户购买的商品信息,用户和商品的关系是多对多关系。
需求1:
查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)。
企业开发中常见明细列表,用户购买商品明细列表,使用resultType将上边查询列映射到pojo输出。
需求2:
查询字段:用户账号、用户名称、购买商品数量、商品明细。
使用resultMap将用户购买的商品明细列表映射到user对象中。

五、总结

1、resultType
作用:
将查询结果按照sql列名pojo属性名一致性映射到pojo中。
使用场合:
常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。


2、resultMap
使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
association:
作用:
将关联查询信息映射到一个pojo对象中。
使用场合:
为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
collection:
作用:
将关联查询信息映射到一个list集合中。
使用场合:
为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
如果使用resultType无法将查询结果映射到list集合中。



posted on 2017-03-28 10:34  想作会飞的鱼  阅读(335)  评论(0编辑  收藏  举报

导航