MyBatis的关联映射之 一对一(嵌套查询/嵌套结果)单击前往
一对多的关系
在一个用户拥有多个订单的案例当中将会使用到一对多的关系映射:在MyBatis当中的resultMap元素的子元素collection就是用于一对多关系映射的。该元素的属性基本与association的属性一致:其中ofType对应的是javaType:它是用于指定实体对象中集合类属性所包含的元素类型。
因此,需要建立一张用户表和一张订单表:其中用户id为1的用户拥有俩个订单:数据库语句如下:
CREATE TABLE tb_user(
id INT(32) PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32),
address VARCHAR(256)
)
INSERT INTO tb_user VALUES('1','李明','中国湖南');
INSERT INTO tb_user VALUES('2','张素','中国广东');
INSERT INTO tb_user VALUES('3','王递','美国洛杉矶');
CREATE TABLE tb_orders(
id INT(32) PRIMARY KEY AUTO_INCREMENT,
number VARCHAR(32) NOT NULL,
user_id INT(32) NOT NULL,
FOREIGN KEY (user_id) REFERENCES tb_user(id)
)
INSERT INTO tb_orders VALUES('1','110','1');
INSERT INTO tb_orders VALUES('2','114','1');
INSERT INTO tb_orders VALUES('3','119','3');
SELECT * FROM tb_user
SELECT * FROM tb_orders
随后在lzq.po这个包下面创建订单持久化类和用户持久化类:将变量进行getset封装以及重写toString方法:(下面代码省略了getset封装的代码)
Orders类
package com.lzq.po;
public class Orders {
private Integer id;
private String number;
@Override
public String toString() {
return "Orders[id=" + id + ", number =" + number + "]";
}
}
User类:在user类当中要引入一个多的关系,使用一个list接口进行对订单编号的保存。
package com.lzq.po;
import java.util.List;
public class User {
private Integer id;
private String username;
private String address;
private List<Orders> OrdersList;
@Override
public String toString() {
return "User[id=" + id + ",username=" + username
+ ",address=" + address + ",OrderList=" + OrdersList + "]";
}
}
再者就是编写映射文件UserMapper.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzq.mapper.UserMapper">
<select id="findUserWithOrders" parameterType="Integer" resultMap="UserWithOrdersResult">
SELECT a.* ,b.id as orders_id,b.number
from tb_user a ,tb_orders b
where a.id =b.user_id and a.id=#{id}
</select>
<resultMap type="User" id="UserWithOrdersResult">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="address" column="address" />
<collection property="OrdersList" ofType="Orders">
<id property="id" column="orders_id"/>
<result property="number" column="number"/>
</collection>
</resultMap>
</mapper>
以及在mybatis-config.xml文件当中进行配置mapper文件:
<mapper resource="com/lzq/mapper/UserMapper.xml" />
定义一个测试方法:与前面测试一对一关系基本同理:查询id为1的用户有几个订单:
@Test
public void findUserTest() {
SqlSession session = MybatisUtils.getSession();
User user = session.selectOne("com.lzq.mapper"+".UserMapper.findUserWithOrders",1);
System.out.println(user);
session.close();
}
效果如下图所示:在给个id为1的值,返回的OrderList的值有俩条,也就是其所对应的俩条订单,这就是一对多关系映射:
在这里通过用户确定订单是一个一对多的关系映射,反过来通过订单确定用户就是一个一对一的关系映射:如何实现呢?如下文所示:
在Orders.java这个类当中新建一个User类的对象:包括其getset方法以及在toString方法里面对其变量进行输出:
private User user;
随后新建一个OrdersMapper,xml映射文件,对其查询的方法进行给定:给定一个订单的id查询出其信息:共有五列信息
<mapper namespace="com.lzq.mapper.OrdersMapper">
<select id="findidByname" parameterType="Integer" resultMap="OrdersResult">
select a.id,a.number,a.user_id,b.username,b.address
from tb_user b ,tb_orders a
where b.id = a.user_id
and a.id=#{id}
select>
<resultMap type="Orders" id="OrdersResult">
<id property="id" column="id">id>
<result property="number" column="number">result>
<association property="user" javaType="User">
<id property="id" column="user_id">id>
<result property="username" column="username">result>
<result property="address" column="address">result>
association>
resultMap>
mapper>
在mybatis-config.xml文件当中引入这个映射文件:
<mapper resource="com/lzq/mapper/OrdersMapper.xml" />
最后使用一对一的关系映射的方法模板进行测试:如下图所示:给定一个订单的id 1,然后查询出其对应的用户信息:
多对多的关系
在前面的基础上,获取订单和订单商品的详情的关系,在这就需要创建一个商品信息表,和一个中间表,并且插入测试的数据:
CREATE TABLE tb_product(
id INT(32) PRIMARY KEY AUTO_INCREMENT,
pname VARCHAR(32),
price DOUBLE
)
INSERT INTO tb_product VALUES ('1','java编程基础','45');
INSERT INTO tb_product VALUES ('2','C编程基础','46.8');
INSERT INTO tb_product VALUES ('3','pyhon编程基础','52.8');
#创建一个中间表,tb_ordersitem
CREATE TABLE tb_ordersitem(
id INT(32) PRIMARY KEY AUTO_INCREMENT,
orders_id INT(32),
product_id INT(32),
FOREIGN KEY (orders_id) REFERENCES tb_orders(id),
FOREIGN KEY (product_id) REFERENCES tb_product(id)
)
INSERT INTO tb_ordersitem VALUE('1','1','1');
INSERT INTO tb_ordersitem VALUE('2','1','3');
INSERT INTO tb_ordersitem VALUE('3','3','3');
一个新的表tb_product就需要对应一个新的实体化的类Product.java,对变量进行封装,以及重写toString方法。
package com.lzq.po;
import java.util.List;
public class Product {
private Integer id;
private String pname;
private Double price;
private List<Orders> orders;
@Override
public String toString() {
return "Product[id=" + id + ",pname=" + pname +
",price=" + price + ",orders" + orders + "]";
}
}
在Orders当中需要添加多的一面:并且对其封装,toString方法当中添加这个变量,用于输出。
private List<Product> product;
早OrdersMapper.xml文件当中添加一条用于多对多的查询的select:
<select id="findProduct" parameterType="Integer"
resultMap="ProductMap">
SELECT * from tb_orders where id=#{id}
select>
<resultMap type="Orders" id="ProductMap">
<id property="id" column="id" />
<result property="number" column="number">result>
<collection property="product" column="id"
ofType="Product" select="com.lzq.mapper.ProductMapper.findProductByid">
collection>
resultMap>
在一个新的ProductMapper.xml文件当中重新定义:如下所示
<select id="findProductByid" parameterType="Integer" resultType="Product">
select * from tb_product where id in(
select product_id from tb_ordersitem where orders_id = #{id}
)
select>
最后定义一个测试方法,如下代码所示:
@Test
public void findOrdersTest() {
SqlSession session = MybatisUtils.getSession();
Orders orders = session.selectOne("com.lzq.mapper"+".OrdersMapper.findProduct",1);
System.out.println(orders);
session.close();
}