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集合中。
Mybatis中的关联映射和查询的更多相关文章
- 【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多
学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一.一对多.多对多,希望多有需要 ...
- 【mybatis深度历险系列】mybatis中的输入映射和输出映射
在前面的博文中,小编介绍了mybatis的框架原理以及入门程序,还有mybatis中开发到的两种方法,原始开发dao的方法和mapper代理方法,今天博文,我们来继续学习mybatis中的相关知识,随 ...
- Mybatis中多表联查,查询出来的字段出现重名,造成数据异常的解决方法!
在做一对多出现的问题,引发的思考:当数据库表中,主表的主键id和明细表的中的字段名相同时怎么办?Mybatis进行自动映射赋值的时候会不会出现异常? 注意:M ...
- Mybatis中动态SQL多条件查询
Mybatis中动态SQL多条件查询 mybatis中用于实现动态SQL的元素有: if:用if实现条件的选择,用于定义where的字句的条件. choose(when otherwise)相当于Ja ...
- mybatis标签之——关联映射
关联关系是面向对象分析.面向对象设计最重要的知识.合理的关联映射将大大简化持久层数据的访问.关联关系大致分为以下三类: 一对一 一对多 多对多 1. 一对一 一对一关系推荐使用唯一主外键关联,即两张表 ...
- Mybatis笔记四:Mybatis中的resultType和resultMap查询操作实例详解
resultType和resultMap只能有一个成立,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,resultMap解决复杂查询是的映射问题.比 ...
- Mybatis 中的转义字符及常用查询
转译符 1.特殊字符转译 < < 小于 > > 大于 & & 与 ' ’ 单引号 " " 双引号 需要注意的是分号是必不可少的. 比如 a ...
- mybatis中一对一关系映射
一对一关系中普通的配置方式 一.多表连接查询语句: <select id="selectStudentWithAddress" parameterType="int ...
- Mybatis中对象关系映射
在实际开发中,实体类之间有一对一.一对多.多对多的关系,所以需要正确配置它们对应关系,Mybatis通过配置文件能够从数据库中获取列数据后自动封装成对象. 如:一个订单Orders类对应一个用户Use ...
随机推荐
- linux让软件停止自动更新
停止自动更新 sudo echo "软件包名 hold" | sudo dpkg --set-selections 比如我想给mysql-server锁定当前版本不更新,命令是: ...
- Spring注释事务失效及解决办法
如果带上事务,那么用annotation方式的事务注解和bean配置,事务会失效,要将service bean配置到xml文件中才行 在主容器中(applicationContext.xml),将C ...
- ElasticSearch文档
1.什么是文档? 程序中大多的实体或对象能够被序列化为包含键值对的JSON对象,键(key)是字段(field)或属性(property)的名字,值(value)可以是字符串.数字.布尔类型.另一个对 ...
- 让Mac支持lrzsz
http://blog.csdn.net/citywolf4/article/details/49071679 https://github.com/mmastrac/iterm2-zmodem
- [转载]CentOS修改用户最大进程数
FROM: http://www.2cto.com/os/201303/192380.html CentOS修改用户最大进程数 一般在/etc/security/limits.conf 中修改最大 ...
- [Tools] Support VS Code Navigation and Autocomplete Based on Webpack Aliases with jsconfig.json
It's common to setup Webpack aliases to make imports much more convenient, but then you lose the abi ...
- android-SQLite数据库MVC关联实例源码(三层架构)
前两天布置下了一个期末练习,其中的重点是两个表之间的SQLite关联操作. 拿到题目,首先需要建库和关联表,下面是代码. 我使用简单的表插入,将数据的提交卸载onCreate方法中,这样不会发生写在主 ...
- 你真的了解装箱(Boxing)和拆箱(Unboxing)吗?
所谓装箱就是装箱是将值类型转换为 object 类型或由此值类型实现的任一接口类型的过程.而拆箱就是反过来了.很多人可能都知道这一点,但是是否真的就很了解boxing和unboxing了呢?可以看下下 ...
- Java学习从入门到精通(2) [转载]
Java Learning Path(二).书籍篇 学习一门新的知识,不可能指望只看一本,或者两本书就能够完全掌握.需要有一个循序渐进的阅读过程.我推荐Oreilly出版的Java系列书籍. 在这里我 ...
- 如何在aspx页面中使用ascx控件(用户自定义的一个控件)?
aspx是页面文件ascx是用户控件,用户控件必须嵌入到aspx中才能使用. ascx是用户控件,相当于模板 其实ascx你可以理解为Html里的一部分代码,只是嵌到aspx里而已,因为aspx内容多 ...