轉自:https://blog.csdn.net/hefenglian/article/details/80699723
訂單商品數據模型
1.1 數據模型分析思路
1、每張表記錄的數據內容
2、每張表重要的字段設置(非空字段、外鍵字段)
3、數據庫級別表與表之間的關係(外鍵關係)
4、表與表之間的業務關係(建立在某個業務意義基礎上去分析)
1.2 數據模型分析
用戶表user:
記錄了購買商品的用戶信息
訂單表:orders
記錄了用戶所創建的訂單(購買商品的訂單)
訂單明細表:orderdetail:
記錄了訂單的詳細信息即購買商品的信息
商品表:items
記錄了商品信息
orders和user:
orders—>user:一個訂單隻由一個用戶創建,一對一
user—->orders:一個用戶可以創建多個訂單,一對多
orders和orderdetail:
orders—>orderdetail:一個訂單可以包括 多個訂單明細,因爲一個訂單可以購買多個商品,每個商品的購買信息在orderdetail記錄,一對多關係
orderdetail–> orders:一個訂單明細只能包括在一個訂單中,一對一
orderdetail和items:
orderdetail—>itesms:一個訂單明細只對應一個商品信息,一對一
items–> orderdetail:一個商品可以包括在多個訂單明細 ,一對多
再分析數據庫級別沒有關係的表之間是否有業務關係:
orders和items:
orders和items之間可以通過orderdetail表建立 關係。
一對一關聯映射
需求:查詢訂單信息,關聯查詢創建訂單的用戶信息
方式一:resultType
第一步:創建pojo—->OrdersCustom
/ * 作用:將sql查詢的 訂單orders和用戶user結果集 全部成功映射到 pojo中,
但是Orders.java中屬性包含不全,因此在寫一個pojo類在繼承Orders基礎上,補充添加其它屬性信息,
注意讓此類繼承包括字段較多的pojo類,比如這裏繼承Orders而不是user,
因爲查詢結果集中user屬性全部有5個,Orders只有3個
*/
package cn.itcast.mybatis.pojo;
public class OrdersCustom extends Orders{
//繼承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;
}
}
第二步:在OrdersMapperCustom.xml中添加如下sql語句
確定查詢的主表:訂單表
確定查詢的關聯表:用戶表
關聯查詢使用內鏈接?還是外鏈接?
:由於orders表中有一個外鍵(user_id),通過外鍵關聯查詢用戶表只能查詢出一條記錄,可以使用內鏈接。
<!-- 第一種:resultType:查詢訂單關聯查詢用戶信息 -->
<select id="findOrderUser" resultType="cn.itcast.mybatis.pojo.OrdersCustom">
SELECT
orders.* ,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
where
orders.user_id=user.id
</select>
第三步:在接口OrdersMapperCustom.java中添加
//查詢訂單關聯查詢用戶信息
public List<OrdersCustom>findOrderUser()throws Exception;
第四步:在OrdersMapperCustomTest.java中添加測試
@Test
public void testFindOrdersUser() throws Exception {
//得到會話sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//創建代理對象
OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
//調用mapper的方法
List<OrdersCustom>list=ordersMapperCustom.findOrderUser();
System.out.println(list);
sqlSession.close();
}
方式二:resultMap
第一步:創建pojo—->OrdersCustom(同上)
第二步:在OrdersMapperCustom.xml中添加如下配置語句
<!-- 定義一個resultMap,訂單查詢 關聯 用戶的 ,將整個查詢的結果映射到cn.itcast.mybatis.pojo.Orders中-->
<resultMap type="cn.itcast.mybatis.pojo.Orders" id="OrdersUserResultMap">
<!-- (1) 配置訂單信息 -->
<!-- 數據庫表orders對應 pojo中的Orders.java -->
<!-- id:唯一標識
column:訂單信息的唯 一標識 列
property:訂單信息的唯 一標識 列所映射到Orders中哪個屬性
result:普通標識 -->
<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"/>
<!-- (2)配置關聯用戶信息 -->
<!-- 數據庫表user對應 pojo中的User.java -->
<!-- association:用於映射關聯查詢單個對象的信息
property:要將關聯查詢的用戶信息映射到Orders中哪個屬性
javaType:映射到user的哪個屬性-->
<association property="user" javaType="cn.itcast.mybatis.pojo.User">
<!-- id:關聯查詢用戶的唯 一標識
column:指定唯 一標識用戶信息的列
result:普通標識
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</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>
第三步:在接口OrdersMapperCustom.java中添加
//可查詢訂單關聯查詢用戶使用resultMap
public List<Orders>findOrdersUserResultMap()throws Exception;
第四步:在OrdersMapperCustomTest.java中測試
@Test
public void testFindOrdersUserResultMap() throws Exception {
//得到會話sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//創建代理對象
OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
//調用mapper的方法,返回映射在pojo 中Orders(裏面補充了User user)
List<Orders>list=ordersMapperCustom.findOrdersUserResultMap();
System.out.println(list);
sqlSession.close();
}
resultType和resultMap實現一對一查詢小結
實現一對一查詢:
resultType:使用resultType實現較爲簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。
如果沒有查詢結果的特殊要求建議使用resultType。
resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。
resultMap可以實現延遲加載,resultType無法實現延遲加載。
一對多關聯映射
需求:查詢訂單orders關聯的訂單明細信息orderdetails
第一步:創建pojo—->Orders.java
//表orders
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//添加user用戶屬性信息,將關聯的用戶信息映射到pojo(User user)的屬性中
private User user;
//添加訂單明細 Orderdetail的屬性信息,將關聯的訂單明細信息映射到此order類
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();
}
//用戶的getter setter方法
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//添加訂單明細的getter setter方法
public List<Orderdetail> getOrderdetails() {
return orderdetails;
}
public void setOrderdetails(List<Orderdetail> orderdetails) {
this.orderdetails = orderdetails;
}
}
使用resultType將上邊的 查詢結果映射到pojo中,訂單信息的就是重複。
對orders映射不能出現重複記錄。
在orders.java類中添加List<orderDetail>orderDetails
屬性。
最終會將訂單信息映射到orders中,訂單所對應的訂單明細映射到orders中的orderDetails屬性中。
第二步:在OrdersMapperCustom.xml中添加如下配置語句
sql語句:
確定主查詢表:訂單表
確定關聯查詢表:訂單明細表
在一對一查詢基礎上添加訂單明細表關聯即可。
<!-- 訂單及訂單明細的resultMap,其中(1)(2)和上面一樣,可以採用繼承 -->
<resultMap type="cn.itcast.mybatis.pojo.Orders" id="OrdersAndOrderDetailResultMap"
extends="OrdersUserResultMap">
<!-- (1) 配置訂單信息 -->
<!-- 數據庫表orders對應 pojo中的Orders.java -->
<!-- (2) 配置關聯用戶信息 -->
<!-- 數據庫表user對應 pojo中的User.java -->
<!-- (3) 配置訂單明細信息 -->
<!-- 數據庫表orderdetail對應 pojo中的Orderdetail.java -->
<!-- 由於一條訂單關聯查詢多個訂單明細,因此採用collection集合映射
collection:將關聯查詢到的多條記錄映射到集合對象中
property:將關聯查詢到的多條記錄映射到cn.itcast.mybatis.pojo.Orders中那個屬性中
ofType:指定映射到list集合屬性中pojo的類型-->
<collection property="orderdetails" ofType="cn.itcast.mybatis.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>
<!--舉例一對多: ResultMap:查詢 訂單 關聯 訂單明細 信息 -->
<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
SELECT
orders.* ,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,<!--別名-->
orderdetail.orders_id,
orderdetail.items_id,
orderdetail.items_num
FROM
orders,
USER,
orderdetail
WHERE
orders.user_id=user.id AND orderdetail.orders_id=orders.id
</select>
第三步:在接口OrdersMapperCustom.java中添加
//查詢訂單關聯訂單明細信息
public List<Orders>findOrdersAndOrderDetailResultMap()throws Exception;
第四步:在OrdersMapperCustomTest.java中添加測試代碼:
@Test
public void testFindOrdersAndOrderDetailResultMap() throws Exception {
//得到會話sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//創建代理對象
OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
//調用mapper的方法,返回映射在pojo 中Orders(裏面補充了Orderdetail orderDetails)
List<Orders>list=ordersMapperCustom.findOrdersAndOrderDetailResultMap();
System.out.println(list);
sqlSession.close();
}
多對多關聯映射
需求:查詢用戶及用戶購買商品信息。
第一步:創建pojo—->User.java,Orders.java,Orderdetail.java,Items.java
映射思路:
- 將用戶信息映射到user中
- 在user類中添加訂單列表屬性
private List<Orders>orderList;
,將用戶創建的訂單映射到ordersList - 在Orders中添加訂單明細列表屬性
private List<Orderdetail>orderdetails;
,將訂單的明細映射到orderdetails - 在Orderdetail中添加Items屬性
private Items items
,將訂單明細所對應的商品映射到Items
第二步:在OrdersMapperCustom.xml中添加如下配置語句
<!-- 查詢用戶和購買商品的resultMap -->
<resultMap type="cn.itcast.mybatis.pojo.User" id="UserAndItemsResultMap">
<!-- (1) 配置用戶信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- (2) 配置訂單信息
一個用戶對應多個訂單,使用collection映射 -->
<collection property="orderList" ofType="cn.itcast.mybatis.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"/>
<!-- (3) 配置訂單明細信息
一個訂單包括 多個訂單明細 -->
<collection property="orderdetails" ofType="cn.itcast.mybatis.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"/>
<!-- (4) 配置商品信息
一個訂單明細對應一個商品-->
<association property="items" javaType="cn.itcast.mybatis.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>
<!-- 舉例多對多:ResultMap:查詢 用戶 購買的商品信息 -->
<select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
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>
第三步:在接口OrdersMapperCustom.java中添加
//查詢用戶購買的商品信息
public List<User>findUserAndItemsResultMap()throws Exception;
第四步:在OrdersMapperCustomTest.java中測試
@Test
public void testFindUserAndItemsResultMap() throws Exception {
//得到會話sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//創建代理對象
OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
//調用mapper的方法,返回映射在pojo 中Orders(裏面補充了Orderdetail orderdetails)
List<User>list=ordersMapperCustom.findUserAndItemsResultMap();
System.out.println(list);
sqlSession.close();
}
延遲加載
定義
resultMap可以實現高級映射(使用association、collection實現一對一及一對多映射),association、collection具備延遲加載功能。
延遲加載:先從單表查詢、需要時再從關聯表去關聯查詢,大大提高 數據庫性能,因爲查詢單表要比關聯查詢多張錶速度要快。
如果查詢訂單並且關聯查詢用戶信息。如果先查詢訂單信息即可滿足要求,當我們需要查詢用戶信息時再查詢用戶信息。把對用戶信息的按需去查詢就是延遲加載。
驗證步驟
需求:查詢訂單並且關聯查詢用戶信息,使用association實現延遲加載
第0步:在SqlMapConfig.xml中開啓延遲加載
mybatis默認沒有開啓延遲加載,需要在SqlMapConfig.xml中setting配置
<settings>
<!-- 開啓延遲加載,注意必須寫在前面 -->
<!-- 打開延遲加載開關 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 將積極加載改爲消極加載即是按需加載 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
第一步:創建pojo—->Orders.java(同上一對一查詢)
第二步:在OrdersMapperCustom.xml中添加如下配置語句
先去執行findOrdersUserLazyLoading,當需要去查詢用戶信息的時候再去執行findUserById,通過resultMap的定義將延遲加載執行配置起來。
<resultMap type="cn.itcast.mybatis.pojo.Orders" id="OrdersUserLazyLoadingResultMap">
<!-- (1) 配置訂單信息 -->
<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"/>
<!-- (2) 實現用戶信息延遲加載 -->
<!-- select:指定延遲加載需要執行的statement的id(是根據user_id查詢用戶信息的statement),
要使用userMapper.xml中findUserById完成根據用戶id(user_id)用戶信息的查詢,
如果findUserById不在本mapper中,則需要加上所在的namespace
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User">
SELECT*FROM USER WHERE id=#{id}
</select>
column:訂單信息中關聯用戶信息查詢的列,是user_id
關聯查詢的sql理解爲:子查詢
select
orders.*,
(select username from user where orders.user_id=user.id)username,
(select sex from user where orders.user_id=user.id)sex
from
orders
-->
<association property="user" javaType="cn.itcast.mybatis.pojo.User"
select="cn.itcast.mybatis.mapper.UserMapper.findUserById"
column="user_id">
</association>
</resultMap>
<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap">
SELECT *FROM orders
</select>
- 關聯查詢用戶信息
通過上邊查詢到的訂單信息中user_id去關聯查詢用戶信息
使用UserMapper.xml中的findUserById
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User">
SELECT*FROM USER WHERE id=#{id}
</select>
第三步:在接口OrdersMapperCustom.java中添加
//查詢訂單關聯查詢用戶,用戶信息是延遲加載
public List<Orders>findOrdersUserLazyLoading()throws Exception;
第四步:測試
//實現訂單查詢用戶,用戶信息的延遲加載
@Test
public void testFindOrdersUserLazyLoading() throws Exception {
//得到會話sqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
//創建代理對象
OrdersMapperCustom ordersMapperCustom=sqlSession.getMapper(OrdersMapperCustom.class);
//查詢訂單信息(單表)
List<Orders>list=ordersMapperCustom.findOrdersUserLazyLoading();
//遍歷訂單列表
for(Orders orders:list){
//執行Orders裏面的getUser()時纔去查詢用戶信息,這裏實現按需加載了
User user=orders.getUser();
System.out.println(user);
}
}
測試思路:
1、執行上邊mapper方法(findOrdersUserLazyLoading),內部去調用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查詢orders信息(單表)。
2、在程序中去遍歷上一步驟查詢出的List<Orders>
,當我們調用Orders中的getUser方法時,開始進行延遲加載。
3、延遲加載,去調用UserMapper.xml中findUserbyId這個方法獲取用戶信息。