SSM 订单操作
1. 表结构分析
1.1.订单表信息描述 orders
序号 | 字段名称 | 字段类型 | 字段描述 |
---|---|---|---|
1 | id | varchar2(32) | 无意义、主键uuid |
2 | orderNum | varchar2(50) | 订单编号 不为空 唯一 |
3 | orderTime | timestamp | 下单时间 |
4 | peopleCount | int | 出行人数 |
5 | orderDesc | varchar2(500) | 订单描述(其它信息) |
6 | payType | int | 支付方式(0 支付宝 1 微信 2其它) |
7 | orderStatus | int | 订单状态(0 未支付 1 已支付) |
8 | productId | int | 产品id 外键 |
9 | memberid | int | 会员(联系人)id 外键 |
productId描述了订单与产品之间的关系。
memberid描述了订单与会员之间的关系。
创建表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;//订单状态(0 未支付 1 已支付)
private String orderStatusStr;//方便显示订单状态
private int peopleCount;//出行人数
private Product product;//产品id 外键
private List<Traveller> travellers;//订单表里的旅客
private Member member;//会员(联系人)id 外键
private Integer payType;//支付方式(0 支付宝 1 微信 2其它)
private String payTypeStr;//方便显示支付方式
private String orderDesc;//订单描述(其它信息)
1.2 会员表信息描述member
订单与会员之间是多对一关系,我们在订单表中创建一个外键来进行关联
序号 | 字段名称 | 字段类型 | 字段描述 |
---|---|---|---|
1 | id | varchar2(32) | 无意义、主键uuid |
2 | name | varchar2(20) | 姓名 |
3 | nickName | varchar2(20) | 昵称 |
4 | phoneNum | varchar2(20) | 电话号码 |
5 | varchar2(50) | 邮箱 |
创建表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 儿童 |
创建表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 |
创建表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方法
//根据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是国内非常优秀的一款开源的mybatis分页插件,它支持基本主流与常用的数据库,例如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
现
在是一个特殊的 dialect 实现类,是分页插件的默认实现类,提供了和以前相同的用法。
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">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<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 分页插件参数介绍
-
helperDialect
:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置
helperDialect
属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
oracle
,mysql
,mariadb
,sqlite
,hsqldb
,postgresql
,db2
,sqlserver
,informix
,h2
,sqlserver201
2
,derby
特别注意:使用SqlServer2012
数据库时,需要手动指定为sqlserver2012
,否则会使用SqlServer2005
的
方式进行分页。 -
reasonable
:分页合理化参数,默认值为false
。当该参数设置为true
时,pageNum<=0
时会查询第一
页,pageNum>pages
(超过总数时),会查询最后一页。默认false
时,直接根据参数进行查询。
本项目只用到了这两个参数,其他参数可以查看具体文档
3.2.4.基本使用
3.2.4.1. PageHelper.startPage 静态方法调用
这种方式是我们要掌握的 在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧
跟在这个方法后的第一个MyBatis 查询方法会被进行分页。
//获取第1页,10条内容,默认查询总数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 {
//参数pageNum 是页码值 参数pageSize 代表是每页显示条数
PageHelper.startPage(page, size);
return ordersDao.findAll();
}
}
3.3.2 Controller
页面请求默认显示第一页,每页4条数据
<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>
页面展示
页面下方可以选择每页显示个数
<div class="form-group form-inline">
总共2 页,共14 条数据。 每页
<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代码实现
function changePageSize() {
//获取下拉框的值
var pageSize = $("#changePageSize").val();
//向服务器发送请求,改变没页显示条数
location.href = "${pageContext.request.contextPath}/orders/findAll.do?page=1&size="
+ pageSize;
}
选择页码
查到的pageInfo
里这里需要知道几个参数
- pageSize-------每页显示数据
- pageNum--------当前页码
- pages----------总页数
<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 {
//根据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">出发城市</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="出发城市"
value="${orders.product.cityName }" 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-a6" value="${orders.product.departureTimeStr}"
readonly="readonly">
</div>
</div>
<div class="col-md-2 title">出游人数</div>
<div class="col-md-4 data">
<input type="text" class="form-control" placeholder="出游人数"
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>
联系人信息/费用信息
<!--联系人信息/--> <!--费用信息-->
<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>