天天看點

MyBatis的關聯映射之 一對多 和 多對多

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檔案:

定義一個測試方法:與前面測試一對一關系基本同理:查詢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的值有倆條,也就是其所對應的倆條訂單,這就是一對多關系映射:

MyBatis的關聯映射之 一對多 和 多對多

在這裡通過使用者确定訂單是一個一對多的關系映射,反過來通過訂單确定使用者就是一個一對一的關系映射:如何實作呢?如下文所示:

在Orders.java這個類當中建立一個User類的對象:包括其getset方法以及在toString方法裡面對其變量進行輸出:

随後建立一個OrdersMapper,xml映射檔案,對其查詢的方法進行給定:給定一個訂單的id查詢出其資訊:共有五列資訊

MyBatis的關聯映射之 一對多 和 多對多
<?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.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檔案當中引入這個映射檔案:

最後使用一對一的關系映射的方法模闆進行測試:如下圖所示:給定一個訂單的id 1,然後查詢出其對應的使用者資訊:

MyBatis的關聯映射之 一對多 和 多對多

多對多的關系

在前面的基礎上,擷取訂單和訂單商品的詳情的關系,在這就需要建立一個商品資訊表,和一個中間表,并且插入測試的資料:

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方法當中添加這個變量,用于輸出。

早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();
	}
           

效果圖如下所示:

MyBatis的關聯映射之 一對多 和 多對多

繼續閱讀