SSM 訂單操作
1. 表結構分析
1.1.訂單表信息描述 orders
| 序號 | 字段名稱 | 字段類型 | 字段描述 |
|---|---|---|---|
| 1 | id | varchar2(32) | 無意義、主鍵uuid |
| 2 | orderNum | varchar2(50) | 訂單編號 不為空 唯一 |
| 3 | orderTime | timestamp | 下單時間 |
| 4 | peopleCount | int | 出行人數(shù) |
| 5 | orderDesc | varchar2(500) | 訂單描述(其它信息) |
| 6 | payType | int | 支付方式(0 支付寶 1 微信 2其它) |
| 7 | orderStatus | int | 訂單狀態(tài)(0 未支付 1 已支付) |
| 8 | productId | int | 產品id 外鍵 |
| 9 | memberid | int | 會員(聯(lián)系人)id 外鍵 |
productId描述了訂單與產品之間的關系。
memberid描述了訂單與會員之間的關系。
創(chuàng)建表sql
CREATE TABLE orders(
id varchar2(32) default SYS_GUID() PRIMARY KEY,
orderNum VARCHAR2(20) NOT NULL UNIQUE,
orderTime timestamp,
peopleCount INT,
orderDesc VARCHAR2(500),
payType INT,
orderStatus INT,
productId varchar2(32),
memberId varchar2(32),
FOREIGN KEY (productId) REFERENCES product(id),
FOREIGN KEY (memberId) REFERENCES member(id)
)
實體類
public class Orders {
private String id;
private String orderNum;//訂單編號 不為空 唯一
private Date orderTime;//下單時間
private String orderTimeStr;//方便顯示時間
private int orderStatus;//訂單狀態(tài)(0 未支付 1 已支付)
private String orderStatusStr;//方便顯示訂單狀態(tài)
private int peopleCount;//出行人數(shù)
private Product product;//產品id 外鍵
private List<Traveller> travellers;//訂單表里的旅客
private Member member;//會員(聯(lián)系人)id 外鍵
private Integer payType;//支付方式(0 支付寶 1 微信 2其它)
private String payTypeStr;//方便顯示支付方式
private String orderDesc;//訂單描述(其它信息)
1.2 會員表信息描述member
訂單與會員之間是多對一關系,我們在訂單表中創(chuàng)建一個外鍵來進行關聯(lián)
| 序號 | 字段名稱 | 字段類型 | 字段描述 |
|---|---|---|---|
| 1 | id | varchar2(32) | 無意義、主鍵uuid |
| 2 | name | varchar2(20) | 姓名 |
| 3 | nickName | varchar2(20) | 昵稱 |
| 4 | phoneNum | varchar2(20) | 電話號碼 |
| 5 | varchar2(50) | 郵箱 |
創(chuàng)建表sql
CREATE TABLE member(
id varchar2(32) default SYS_GUID() PRIMARY KEY,
NAME VARCHAR2(20),
nickname VARCHAR2(20),
phoneNum VARCHAR2(20),
email VARCHAR2(20)
)
實體類
public class Member {
private String id;
private String name;//姓名
private String nickname;//昵稱
private String phoneNum;//電話號碼
private String email;//郵箱
1.3.旅客表信息描述 traveller
| 序號 | 字段名稱 | 字段類型 | 字段描述 |
|---|---|---|---|
| 1 | id | varchar2(32) | 無意義、主鍵uuid |
| 2 | name | varchar2(20) | 姓名 |
| 3 | sex | varchar2(20) | 性別 |
| 4 | phoneNum | varchar2(20) | 電話號碼 |
| 5 | credentialsType | int | 證件類型 0身份證 1護照 2軍官證 |
| 6 | credentialsNum | varchar2(50) | 證件號碼 |
| 7 | travellerType | int | 旅客類型(人群) 0 成人 1 兒童 |
創(chuàng)建表sql
CREATE TABLE traveller(
id varchar2(32) default SYS_GUID() PRIMARY KEY,
NAME VARCHAR2(20),
sex VARCHAR2(20),
phoneNum VARCHAR2(20),
credentialsType INT,
credentialsNum VARCHAR2(50),
travellerType INT
)
實體類
public class Traveller {
private String id;
private String name;//姓名
private String sex;//性別
private String phoneNum;//電話號碼
private Integer credentialsType;//證件類型 0身份證 1護照 2軍官證
private String credentialsTypeStr;//
private String credentialsNum;//證件號碼
private Integer travellerType;//旅客類型(人群) 0 成人 1 兒童
private String travellerTypeStr;//
//省略getter/setter
}
旅客與訂單之間是多對多關系,所以我們需要一張中間表(order_traveller)來描述
| 序號 | 字段名稱 | 字段類型 | 字段描述 |
|---|---|---|---|
| 1 | orderId | varchar2(32) | 訂單id |
| 2 | travellerId | varchar2(32) | 旅客id |
創(chuàng)建表sql
CREATE TABLE order_traveller(
orderId varchar2(32),
travellerId varchar2(32),
PRIMARY KEY (orderId,travellerId),
FOREIGN KEY (orderId) REFERENCES orders(id),
FOREIGN KEY (travellerId) REFERENCES traveller(id)
)
2. 訂單查詢
2.1 訂單查詢頁面 order-list.jsp
aside.jsp頁面跳轉
<li id="system-setting">
<a href="${pageContext.request.contextPath}/orders/findAll.do?">
<i class="fa fa-circle-o"></i> 訂單管理</a>
</li>
2.2 Controller
//查詢全部訂單---未分頁
@RequestMapping("/findAll.do")
public ModelAndView findAll() throws Exception {
ModelAndView mv = new ModelAndView();
List<Orders> ordersList = ordersService.findAll();
mv.addObject("ordersList", ordersList);
mv.setViewName("orders-list");
return mv;
}
2.3 Dao
@Select("select * from orders")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "orderNum", column = "orderNum"),
@Result(property = "orderTime", column = "orderTime"),
@Result(property = "orderStatus", column = "orderStatus"),
@Result(property = "peopleCount", column = "peopleCount"),
@Result(property = "peopleCount", column = "peopleCount"),
@Result(property = "payType", column = "payType"),
@Result(property = "orderDesc", column = "orderDesc"),
@Result(property = "product", column = "productId", javaType = Product.class, one = @One(select = "com.rgh.ssm.dao.IProductDao.findById")),
})
public List<Orders> findAll() throws Exception;
一個訂單里有一個產品,按照這樣的需求來做
需要IProductDao有findById方法
//根據(jù)id查詢產品
@Select("select * from product where id=#{id}")
public Product findById(String id) throws Exception;
2.4 在orders-list.jsp的顯示
<tbody>
<c:forEach items="${ordersList}" var="orders">
<tr>
<td><input name="ids" type="checkbox"></td>
<td>${orders.id }</td>
<td>${orders.orderNum }</td>
<td>${orders.product.productName }</td>
<td>${orders.product.productPrice }</td>
<td>${orders.orderTimeStr }</td>
<td class="text-center">${orders.orderStatusStr }</td>
<td class="text-center">
<button type="button" class="btn bg-olive btn-xs">訂單</button>
<button type="button" class="btn bg-olive btn-xs" onclick="location.href='${pageContext.request.contextPath}/orders/findById.do?id=${orders.id}'">詳情</button>
<button type="button" class="btn bg-olive btn-xs">編輯</button>
</td>
</tr>
</c:forEach>
</tbody>
3. 訂單分頁查詢
3.1 PageHelper介紹
PageHelper是國內非常優(yōu)秀的一款開源的mybatis分頁插件,它支持基本主流與常用的數(shù)據(jù)庫,例如mysql、
oracle、mariaDB、DB2、SQLite、Hsqldb等
3.2 PageHelper使用
3.2.1.集成
引入分頁插件有下面2種方式,推薦使用 Maven 方式。
3.2.1.1. 引入 Jar 包
你可以從下面的地址中下載最新版本的 jar 包
由于使用了sql 解析工具,你還需要下載 jsqlparser.jar
3.2.1.2. 使用 Maven
在 pom.xml 中添加如下依賴
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>最新版本</version><!--本項目這里是5.1.2-->
</dependency>
3.2. 2.配置
特別注意,新版攔截器是 com.github.pagehelper.PageInterceptor 。 com.github.pagehelper.PageHelper 現(xiàn)
在是一個特殊的 dialect 實現(xiàn)類,是分頁插件的默認實現(xiàn)類,提供了和以前相同的用法。
3.2.2.1. 在 MyBatis 配置 xml 中配置攔截器插件
<!--
plugins在配置文件中的位置必須符合要求,否則會報錯,順序如下:
properties?, settings?,
typeAliases?, typeHandlers?,
objectFactory?,objectWrapperFactory?,
plugins?,
environments?, databaseIdProvider?, mappers?
-->
<plugins>
<!-- com.github.pagehelper為PageHelper類所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置參數(shù),后面會有所有的參數(shù)介紹 -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
3.2.2.2. 在 Spring 配置文件中配置攔截器插件
使用 spring 的屬性配置方式,可以使用 plugins 屬性像下面這樣配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 傳入PageHelper的插件 -->
<property name="plugins">
<array>
<!-- 傳入插件的對象 -->
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">oracle</prop>
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
3.2.3 分頁插件參數(shù)介紹
-
helperDialect:分頁插件會自動檢測當前的數(shù)據(jù)庫鏈接,自動選擇合適的分頁方式。 你可以配置
helperDialect屬性來指定分頁插件使用哪種方言。配置時,可以使用下面的縮寫值:
oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver201
2,derby
特別注意:使用SqlServer2012數(shù)據(jù)庫時,需要手動指定為sqlserver2012,否則會使用SqlServer2005的
方式進行分頁。 -
reasonable:分頁合理化參數(shù),默認值為false。當該參數(shù)設置為true時,pageNum<=0時會查詢第一
頁,pageNum>pages(超過總數(shù)時),會查詢最后一頁。默認false時,直接根據(jù)參數(shù)進行查詢。
本項目只用到了這兩個參數(shù),其他參數(shù)可以查看具體文檔
3.2.4.基本使用
3.2.4.1. PageHelper.startPage 靜態(tài)方法調用
這種方式是我們要掌握的 在你需要進行分頁的 MyBatis 查詢方法前調用PageHelper.startPage 靜態(tài)方法即可,緊
跟在這個方法后的第一個MyBatis 查詢方法會被進行分頁。
//獲取第1頁,10條內容,默認查詢總數(shù)count
PageHelper.startPage(1, 10);
//緊跟著的第一個select方法會被分頁
List<Country> list = countryMapper.selectIf(1);
3.3 訂單分頁查詢
3.3.1 Service
@Service
@Transactional
public class OrdersServiceImpl implements IOrdersService {
@Autowired
private IOrdersDao ordersDao;
@Override
public List<Orders> findAll(int page, int size) throws Exception {
//參數(shù)pageNum 是頁碼值 參數(shù)pageSize 代表是每頁顯示條數(shù)
PageHelper.startPage(page, size);
return ordersDao.findAll();
}
}
3.3.2 Controller
頁面請求默認顯示第一頁,每頁4條數(shù)據(jù)
<li id="system-setting">
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=1&size=4">
<i class="fa fa-circle-o"></i> 訂單管理</a>
</li>
Controller類
@RequestMapping("/findAll.do")
public ModelAndView findAll(@RequestParam(name = "page", required = true, defaultValue = "1") int page, @RequestParam(name = "size", required = true, defaultValue = "4") int size) throws Exception {
ModelAndView mv = new ModelAndView();
List<Orders> ordersList = ordersService.findAll(page, size);
//PageInfo就是一個分頁Bean
PageInfo pageInfo = new PageInfo(ordersList);
mv.addObject("pageInfo", pageInfo);
mv.setViewName("orders-page-list");
return mv;
}
3.3.3 orders-page-list.jsp頁面
<tbody>
<c:forEach items="${pageInfo.list}" var="orders">
<tr>
<td><input name="ids" type="checkbox"></td>
<td>${orders.id }</td>
<td>${orders.orderNum }</td>
<td>${orders.product.productName }</td>
<td>${orders.product.productPrice }</td>
<td>${orders.orderTimeStr }</td>
<td class="text-center">${orders.orderStatusStr }</td>
<td class="text-center">
<button type="button" class="btn bg-olive btn-xs">訂單</button>
<button type="button" class="btn bg-olive btn-xs" onclick="location.href='${pageContext.request.contextPath}/orders/findById.do?id=${orders.id}'">詳情</button>
<button type="button" class="btn bg-olive btn-xs">編輯</button>
</td>
</tr>
</c:forEach>
</tbody>
頁面展示
頁面下方可以選擇每頁顯示個數(shù)
<div class="form-group form-inline">
總共2 頁,共14 條數(shù)據(jù)。 每頁
<select class="form-control" id="changePageSize" onchange="changePageSize()">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select> 條
</div>
用js代碼實現(xiàn)
function changePageSize() {
//獲取下拉框的值
var pageSize = $("#changePageSize").val();
//向服務器發(fā)送請求,改變沒頁顯示條數(shù)
location.href = "${pageContext.request.contextPath}/orders/findAll.do?page=1&size="
+ pageSize;
}
選擇頁碼
查到的pageInfo里這里需要知道幾個參數(shù)
- pageSize-------每頁顯示數(shù)據(jù)
- pageNum--------當前頁碼
- pages----------總頁數(shù)
<ul class="pagination">
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=1&size=${pageInfo.pageSize}" aria-label="Previous">首頁</a>
</li>
<li><a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}">上一頁</a></li>
<c:forEach begin="1" end="${pageInfo.pages}" var="pageNum">
<li><a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageNum}&size=${pageInfo.pageSize}">${pageNum}</a></li>
</c:forEach>
<li><a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pageNum+1}&size=${pageInfo.pageSize}">下一頁</a></li>
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pages}&size=${pageInfo.pageSize}" aria-label="Next">尾頁</a>
</li>
</ul>
4.訂單詳情
在order-list.jsp頁面上對"詳情"添加鏈接
<button type="button" class="btn bg-olive btn-xs" onclick="location.href='${pageContext.request.contextPath}/orders/findById.do?id=${orders.id}'">詳情</button>
4.1 訂單詳情 order-show.jsp
詳情頁面需要訂單信息,產品信息,會員信息,游客信息
訂單表與產品表是一對一,與會員表是一對一,與游客表是多對多通過中間表來查詢
4.2 Controller
@RequestMapping("/findById.do")
public ModelAndView findById(@RequestParam(name = "id", required = true) String ordersId) throws Exception {
ModelAndView mv = new ModelAndView();
Orders orders = ordersService.findById(ordersId);
System.out.println(orders.getMember());
mv.addObject("orders",orders);
mv.setViewName("orders-show");
return mv;
}
4.3 Dao
//多表操作
@Select("select * from orders where id=#{ordersId}")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "orderNum", column = "orderNum"),
@Result(property = "orderTime", column = "orderTime"),
@Result(property = "orderStatus", column = "orderStatus"),
@Result(property = "peopleCount", column = "peopleCount"),
@Result(property = "peopleCount", column = "peopleCount"),
@Result(property = "payType", column = "payType"),
@Result(property = "orderDesc", column = "orderDesc"),
@Result(property = "product", column = "productId", javaType = Product.class, one = @One(select = "com.rgh.ssm.dao.IProductDao.findById")),
@Result(property = "member",column = "memberId",javaType = Member.class,one = @One(select = "com.rgh.ssm.dao.IMemberDao.findById")),
@Result(property = "travellers",column = "id",javaType =java.util.List.class,many = @Many(select = "com.rgh.ssm.dao.ITravellerDao.findByOrdersId"))
})
public Orders findById(String ordersId) throws Exception;
這里需要在IMemberDao,ITravellerDao,IProductDao中加上findById方法
public interface IMemberDao {
@Select("select * from member where id=#{id}")
public Member findById(String id) throws Exception;
}
public interface IProductDao {
//根據(jù)id查詢產品
@Select("select * from product where id=#{id}")
public Product findById(String id) throws Exception;
}
public interface ITravellerDao {
@Select("select * from traveller where id in (select travellerId from order_traveller where orderId=#{ordersId})")
public List<Traveller> findByOrdersId(String ordersId) throws Exception;
}
4.4 orders-show.jsp的展示
游客信息
<thead>
<tr>
<th class="">人群</th>
<th class="">姓名</th>
<th class="">性別</th>
<th class="">手機號碼</th>
<th class="">證件類型</th>
<th class="">證件號碼</th>
</tr>
</thead>
<tbody>
<c:forEach var="traveller" items="${orders.travellers}">
<tr>
<td>${traveller.travellerTypeStr}</td>
<td><input type="text" size="10" value="${traveller.name }"
readonly="readonly"></td>
<td><input type="text" size="10" value="${traveller.sex }"
readonly="readonly"></td>
<td><input type="text" size="20"
value="${traveller.phoneNum }" readonly="readonly"></td>
<td><input type="text" size="15"
value="${traveller.credentialsTypeStr}" readonly="readonly"></td>
<td><input type="text" size="28"
value="${traveller.credentialsNum }" readonly="readonly"></td>
</tr>
</c:forEach>
</tbody>
訂單信息
<div class="panel panel-default">
<div class="panel-heading">訂單信息</div>
<div class="row data-type">
<div class="col-md-2 title">訂單編號</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="訂單編號"
value="${orders.orderNum }" readonly="readonly">
</div>
<div class="col-md-2 title">下單時間</div>
<div class="col-md-4 data">
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" class="form-control pull-right"
id="datepicker-a3" readonly="readonly"
value="${orders.orderTimeStr}">
</div>
</div>
<div class="col-md-2 title">路線名稱</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="路線名稱"
value="${orders.product.productName }" readonly="readonly">
</div>
<div class="col-md-2 title">出發(fā)城市</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="出發(fā)城市"
value="${orders.product.cityName }" readonly="readonly">
</div>
<div class="col-md-2 title">出發(fā)時間</div>
<div class="col-md-4 data">
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input type="text" class="form-control pull-right"
id="datepicker-a6" value="${orders.product.departureTimeStr}"
readonly="readonly">
</div>
</div>
<div class="col-md-2 title">出游人數(shù)</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="出游人數(shù)"
value="${orders.peopleCount}" readonly="readonly">
</div>
<div class="col-md-2 title rowHeight2x">其他信息</div>
<div class="col-md-10 data rowHeight2x">
<textarea class="form-control" rows="3" placeholder="其他信息">
${orders.orderDesc }
</textarea>
</div>
</div>
</div>
聯(lián)系人信息/費用信息
<!--聯(lián)系人信息/--> <!--費用信息-->
<c:if test="${orders.orderStatus==1}">
<div class="panel panel-default">
<div class="panel-heading">費用信息</div>
<div class="row data-type">
<div class="col-md-2 title">支付方式</div>
<div class="col-md-4 data text">在線支付-${orders.payTypeStr}</div>
<div class="col-md-2 title">金額</div>
<div class="col-md-4 data text">¥${orders.product.productPrice}</div>
</div>
</div>
</c:if>