我们接下来做我们项目的下一个环节,就是出口报运的业务,首先我们来看看两个设计方式
a)大型项目设计方式
传统设计方式,基于对象关联,数据量小时,系统无碍;当数据随着系统的使用,线性增长,系统变的越来越慢,到达一定数据量时,性能急剧下降。
b)新的设计方式:打断设计
在表中增加一个字段,这个字段用来存储关联表的主键集合;在报运业务中要查询合同下的货物信息。直接通过这个关联字段,利用in子查询直接去查询货物表,这样查询效率提高很多。而且数据量越大,查询效率越高。这种方式,业务关联层级越多,这种设计方式的性能体现越高。而且通过这种方式可以实现跳跃查询。
那么打断设计具体如何实现呢?我们通过写我们的出口报运项目来实践它。
1,货运管理报运新增
用户要选择多个合同,然后进行报运。(体现出业务关联)
报运新增时,报运专责只能看到已上报的购销合同。
我们先把我们的“报运单”、“报运下的货物”、“报运下的附件”三张表导入到PL/SQL中:
我们接下来开始做后台,首先编写出口报运的实体类:
下面做我们的映射文件ExportMapper.xml,我们添加增删查修的SQL语句:
接下来写我们的Dao层:
ExportDao.java:
ExportDaoImpl.java:
都继承了BaseDao和BaseDaoImpl(包含了基本的增删改查的方法以及方法的实现),回顾一下BaseDao和BaseDaoImpl:
BaseDao:
BaseDaoImpl:
然后使我们的Service层:
ExportService.java:
ExportServiceImpl:
我们的update方法和插入方法后期还要继续完善,这里我们先简单的写一下。
然后使我们的Controller层:
我们在beans-service.xml中注入exportService:
我们这里先写一个获取出口报运信息列表的方法,然后我们写一个Jsp页面来显示出口报运信息列表:
jExportList.jsp:
我们的数据入口,在left.jsp中添加“出口报运”的链接:
我们先加一些测试数据,然后点击出口报运,获取列表:
a)大型项目设计方式
传统设计方式,基于对象关联,数据量小时,系统无碍;当数据随着系统的使用,线性增长,系统变的越来越慢,到达一定数据量时,性能急剧下降。
b)新的设计方式:打断设计
在表中增加一个字段,这个字段用来存储关联表的主键集合;在报运业务中要查询合同下的货物信息。直接通过这个关联字段,利用in子查询直接去查询货物表,这样查询效率提高很多。而且数据量越大,查询效率越高。这种方式,业务关联层级越多,这种设计方式的性能体现越高。而且通过这种方式可以实现跳跃查询。
那么打断设计具体如何实现呢?我们通过写我们的出口报运项目来实践它。
1,货运管理报运新增
用户要选择多个合同,然后进行报运。(体现出业务关联)
报运新增时,报运专责只能看到已上报的购销合同。
我们先把我们的“报运单”、“报运下的货物”、“报运下的附件”三张表导入到PL/SQL中:
- create table EXPORT_C (
- EXPORT_ID VARCHAR2(40) not null,
- INPUT_DATE TIMESTAMP,
- CONTRACT_IDS VARCHAR2(500),
- CUSTOMER_CONTRACT VARCHAR2(200),
- LCNO VARCHAR2(10),
- CONSIGNEE VARCHAR2(100),
- MARKS VARCHAR2(1000),
- REMARK VARCHAR2(100),
- SHIPMENT_PORT VARCHAR2(100),
- DESTINATION_PORT VARCHAR2(100),
- TRANSPORT_MODE VARCHAR2(10),
- PRICE_CONDITION VARCHAR2(10),
- STATE INT,
- GROSS_WEIGHT NUMBER(5,2),
- NET_WEIGHT NUMBER(5,2),
- MEASUREMENT NUMBER(8,2),
- CREATE_BY VARCHAR2(40),
- CREATE_DEPT VARCHAR2(40),
- CREATE_TIME TIMESTAMP,
- constraint PK_EXPORT_C primary key (EXPORT_ID)
- );
- create table EXPORT_PRODUCT_C (
- EXPORT_PRODUCT_ID VARCHAR2(40) not null,
- EXPORT_ID VARCHAR2(40),
- FACTORY_ID VARCHAR2(40),
- FACTORY_NAME VARCHAR2(50),
- PRODUCT_NO VARCHAR2(50),
- PACKING_UNIT VARCHAR2(10),
- CNUMBER INT,
- BOX_NUM INT,
- GROSS_WEIGHT NUMBER(8,2),
- NET_WEIGHT NUMBER(8,2),
- SIZE_LENGTH NUMBER(8,2),
- SIZE_WIDTH NUMBER(8,2),
- SIZE_HEIGHT NUMBER(8,2),
- EX_PRICE NUMBER(8,2),
- PRICE NUMBER(10,2),
- TAX NUMBER(8,2),
- ORDER_NO INT,
- constraint PK_EXPORT_PRODUCT_C primary key (EXPORT_PRODUCT_ID)
- );
- create table EXT_EPRODUCT_C (
- EXT_EPRODUCT_ID VARCHAR2(40) not null,
- EXPORT_PRODUCT_ID VARCHAR2(40),
- FACTORY_ID VARCHAR2(40),
- FACTORY_NAME VARCHAR2(50),
- CTYPE INT,
- PRODUCT_NO VARCHAR2(50),
- PRODUCT_IMAGE VARCHAR2(200),
- PRODUCT_DESC VARCHAR2(600),
- CNUMBER INT,
- PACKING_UNIT VARCHAR2(10),
- PRICE NUMBER(10,2),
- AMOUNT NUMBER(10,2),
- PRODUCT_REQUEST VARCHAR2(2000),
- ORDER_NO INT,
- constraint PK_EXT_EPRODUCT_C primary key (EXT_EPRODUCT_ID)
- );
创建成功:
我们接下来开始做后台,首先编写出口报运的实体类:
- package cn.hpu.jk.domain;
- import java.util.Date;
- public class Export {
- private String id;
- private Date inputDate;
- private String epnum;
- private String extnum;
- private String contractIds;//打断设计,合同的ID集合
- private String customerContract;//合同及确认书号
- private String lcno;//信用证号
- private String consignee;//收货人及地址
- private String marks;//唛头
- private String remark;
- private String shipmentPort;//装运港
- private String destinationPort;//目的港
- private String transportMode;//运输方式
- private String priceCondition;//价格条件
- //state状态,为了流程跟踪(0-草稿,1-已上报,2-装修,3-委托,4-发票,5-财务)
- private Integer state;
- private Double grossWeight; //毛重
- private Double netWeight;//净重
- private String measurement;//体积(中间计算)
- private String createBy;
- private String creatDept;
- private java.util.Date creatTime;
- //get和set方法省略
- }
下面做我们的映射文件ExportMapper.xml,我们添加增删查修的SQL语句:
- <?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="cn.hpu.jk.mapper.ExportMapper">
- <resultMap type="cn.hpu.jk.domain.Export" id="exportRM">
- <id property="id" column="EXPORT_ID"/>
- <!-- 虚拟字段 -->
- <result property="epnum" column="EPNUM"/>
- <result property="extnum" column="EXTNUM"/>
- <result property="inputDate" column="INPUT_DATE"/>
- <result property="contractIds" column="CONTRACT_IDS"/>
- <result property="customerContract" column="CUSTOMER_CONTRACT"/>
- <result property="lcno" column="LCNO"/>
- <result property="consignee" column="CONSIGNEE"/>
- <result property="marks" column="MARKS"/>
- <result property="remark" column="REMARK"/>
- <result property="shipmentPort" column="SHIPMENT_PORT"/>
- <result property="destinationPort" column="DESTINATION_PORT"/>
- <result property="transportMode" column="TRANSPORT_MODE"/>
- <result property="priceCondition" column="PRICE_CONDITION"/>
- <result property="grossWeight" column="GROSS_WEIGHT"/>
- <result property="netWeight" column="NET_WEIGHT"/>
- <result property="measurement" column="MEASUREMENT"/>
- <result property="state" column="STATE"/>
- <result property="createBy" column="CREATE_BY"/>
- <result property="createDept" column="CREATE_DEPT"/>
- <result property="createTime" column="CREATE_TIME"/>
- </resultMap>
- <select id="find" parameterType="map" resultMap="exportRM">
- select
- (select count(*) from export_product_c
- where export_id=e.export_id) as epnum,
- (select count(*) from ext_eproduct_c
- where export_product_id in
- (select export_product_id from export_product_c
- where export_id=e.export_id)
- )as extnum,
- e.export_id,e.input_date,e.contract_ids,e.customer_contract,e.lcno,
- e.consignee,e.marks,e.remark,e.shipment_port,e.destination_port,
- e.transport_mode,e.price_condition,e.gross_weight,e.net_weight,e.measurement,e.state
- from export_c e
- </select>
- <select id="get" parameterType="cn.hpu.jk.domain.Export" resultMap="exportRM">
- select * from export_c
- where export_id=#{pid}
- </select>
- <insert id="insert" parameterType="cn.hpu.jk.domain.Export">
- insert into export_c
- (EXPORT_ID,INPUT_DATE,CONTRACT_IDS,CUSTOMER_CONTRACT,LCNO,CONSIGNEE,MARKS,
- REMARK,SHIPMENT_PORT,DESTINATION_PORT,TRANSPORT_MODE,PRICE_CONDITION,
- GROSS_WEIGHT,NET_WEIGHT,MEASUREMENT,STATE,CREATE_BY,CREATE_DEPT,CREATE_TIME)
- values
- (
- #{id},
- #{inputDate, jdbcType=TIMESTAMP},
- #{contractIds, jdbcType=VARCHAR},
- #{customerContract, jdbcType=VARCHAR},
- #{lcno, jdbcType=VARCHAR},
- #{consignee, jdbcType=VARCHAR},
- #{marks, jdbcType=VARCHAR},
- #{remark, jdbcType=VARCHAR},
- #{shipmentPort, jdbcType=VARCHAR},
- #{destinationPort, jdbcType=VARCHAR},
- #{transportMode, jdbcType=VARCHAR},
- #{priceCondition, jdbcType=VARCHAR},
- #{grossWeight, jdbcType=DOUBLE},
- #{netWeight, jdbcType=DOUBLE},
- #{measurement, jdbcType=DOUBLE},
- #{state, jdbcType=INTEGER},
- #{createBy, jdbcType=VARCHAR},
- #{createDept, jdbcType=VARCHAR},
- #{createTime, jdbcType=TIMESTAMP}
- )
- </insert>
- <update id="update" parameterType="cn.hpu.jk.domain.Export">
- update export_c
- <set>
- <if test="inputDate != null"> INPUT_DATE=#{inputDate},</if>
- <if test="contractIds != null"> CONTRACT_IDS=#{contractIds},</if>
- <if test="customerContract != null"> CUSTOMER_CONTRACT=#{customerContract},</if>
- <if test="lcno != null"> LCNO=#{lcno},</if>
- <if test="consignee != null"> CONSIGNEE=#{consignee},</if>
- <if test="marks != null"> MARKS=#{marks},</if>
- <if test="remark != null"> REMARK=#{remark},</if>
- <if test="shipmentPort != null"> SHIPMENT_PORT=#{shipmentPort},</if>
- <if test="destinationPort != null"> DESTINATION_PORT=#{destinationPort},</if>
- <if test="transportMode != null"> TRANSPORT_MODE=#{transportMode},</if>
- <if test="priceCondition != null"> PRICE_CONDITION=#{priceCondition},</if>
- <if test="grossWeight != null"> GROSS_WEIGHT=#{grossWeight},</if>
- <if test="netWeight != null"> NET_WEIGHT=#{netWeight},</if>
- <if test="measurement != null"> MEASUREMENT=#{measurement},</if>
- </set>
- where export_id=#{id}
- </update>
- <!-- 删除一条 -->
- <delete id="deleteById" parameterType="string">
- delete from export_c
- where export_id=#{pid}
- </delete>
- <!-- 删除多条(一维字符串数组) -->
- <delete id="delete" parameterType="string">
- delete from export_c
- where export_id in
- <foreach collection="array" item="id" open="(" close=")" separator=",">
- #{id}
- </foreach>
- </delete>
- <!-- 修改状态 -->
- <update id="updateState" parameterType="map">
- update export_c set state=#{state}
- where export_id in
- <foreach collection="ids" item="id" open="(" close=")" separator=",">
- #{id}
- </foreach>
- </update>
- </mapper>
接下来写我们的Dao层:
ExportDao.java:
- package cn.hpu.jk.dao;
- import java.util.Map;
- import cn.hpu.jk.domain.Contract;
- public interface ExportDao extends BaseDao<Export>{
- //我们这里可以直接使用继承的BaseDao的增删改查方法
- //创建一系列其它Dao的原因是因为其它Dao有可能需要拓展
- public void updateState(Map map);//修改状态
- }
ExportDaoImpl.java:
- package cn.hpu.jk.dao.impl;
- import java.util.Map;
- import org.springframework.stereotype.Repository;
- import cn.hpu.jk.dao.ExportDao;
- import cn.hpu.jk.domain.Export;
- @Repository //为了包扫描的时候这个Dao被扫描到
- public class ExportDaoImpl extends BaseDaoImpl<Export> implements ExportDao{
- public ExportDaoImpl(){
- //设置命名空间
- super.setNs("cn.hpu.jk.mapper.ExportMapper");
- }
- @Override
- public void updateState(Map map) {
- super.getSqlSession().update(super.getNs()+".updateState", map);
- }
- }
都继承了BaseDao和BaseDaoImpl(包含了基本的增删改查的方法以及方法的实现),回顾一下BaseDao和BaseDaoImpl:
BaseDao:
- package cn.hpu.jk.dao;
- import java.io.Serializable;
- import java.util.List;
- import java.util.Map;
- import cn.hpu.jk.pagination.Page;
- /**
- * @Description: 泛型类,基础的DAO接口
- */
- public interface BaseDao<T> {
- public List<T> findPage(Page page); //分页查询
- public List<T> find(Map paraMap); //带条件查询,条件可以为null,既没有条件;返回list对象集合
- public T get(Serializable id); //只查询一个,常用于修改
- public void insert(T entity); //插入,用实体作为参数
- public void update(T entity); //修改,用实体作为参数
- public void deleteById(Serializable id); //按id删除,删除一条;支持整数型和字符串类型ID
- public void delete(Serializable[] ids); //批量删除;支持整数型和字符串类型ID
- }
BaseDaoImpl:
- package cn.hpu.jk.dao.impl;
- import java.io.Serializable;
- import java.util.List;
- import java.util.Map;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.mybatis.spring.support.SqlSessionDaoSupport;
- import org.springframework.beans.factory.annotation.Autowired;
- import cn.hpu.jk.dao.BaseDao;
- import cn.hpu.jk.pagination.Page;
- public abstract class BaseDaoImpl<T> extends SqlSessionDaoSupport implements BaseDao<T>{
- @Autowired
- //mybatis-spring 1.0无需此方法;mybatis-spring1.2必须注入。
- public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){
- super.setSqlSessionFactory(sqlSessionFactory);
- }
- private String ns; //命名空间
- public String getNs() {
- return ns;
- }
- public void setNs(String ns) {
- this.ns = ns;
- }
- public List<T> findPage(Page page){
- List<T> oList = this.getSqlSession().selectList(ns + ".findPage", page);
- return oList;
- }
- public List<T> find(Map map) {
- List<T> oList = this.getSqlSession().selectList(ns + ".find", map);
- return oList;
- }
- public T get(Serializable id) {
- return this.getSqlSession().selectOne(ns + ".get", id);
- }
- public void insert(T entity) {
- this.getSqlSession().insert(ns + ".insert", entity);
- }
- public void update(T entity) {
- this.getSqlSession().update(ns + ".update", entity);
- }
- public void deleteById(Serializable id) {
- this.getSqlSession().delete(ns + ".deleteById", id);
- }
- public void delete(Serializable[] ids) {
- this.getSqlSession().delete(ns + ".delete", ids);
- }
- }
然后使我们的Service层:
ExportService.java:
- package cn.hpu.jk.service;
- import java.io.Serializable;
- import java.util.List;
- import java.util.Map;
- import cn.hpu.jk.domain.Export;
- import cn.hpu.jk.pagination.Page;
- public interface ExportService {
- public List<Export> findPage(Page page); //分页查询
- public List<Export> find(Map paraMap); //带条件查询,条件可以为null,既没有条件;返回list对象集合
- public Export get(Serializable id); //只查询一个,常用于修改
- public void insert(Export export); //插入,用实体作为参数
- public void update(Export export); //修改,用实体作为参数
- public void deleteById(Serializable id); //按id删除,删除一条;支持整数型和字符串类型ID
- public void delete(Serializable[] ids); //批量删除;支持整数型和字符串类型ID
- public void submit(Serializable[] ids);//上报
- public void cancel(Serializable[] ids);//取消
- }
ExportServiceImpl:
- package cn.hpu.jk.service.impl;
- import java.io.Serializable;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.annotation.Resource;
- import cn.hpu.jk.dao.ExportDao;
- import cn.hpu.jk.domain.Export;
- import cn.hpu.jk.pagination.Page;
- import cn.hpu.jk.service.ExportService;
- public class ExportServiceImpl implements ExportService{
- @Resource
- ExportDao exportDao;
- @Override
- public List<Export> find(Map paraMap) {
- // TODO Auto-generated method stub
- return exportDao.find(paraMap);
- }
- @Override
- public List<Export> findPage(Page page) {
- // TODO Auto-generated method stub
- return exportDao.findPage(page);
- }
- @Override
- public Export get(Serializable id) {
- // TODO Auto-generated method stub
- return exportDao.get(id);
- }
- @Override
- public void insert(Export export) {
- exportDao.insert(export);
- }
- @Override
- public void update(Export export) {
- exportDao.update(export);
- }
- @Override
- public void delete(Serializable[] ids) {
- exportDao.delete(ids);
- }
- @Override
- public void deleteById(Serializable id) {
- exportDao.deleteById(id);
- }
- @Override
- public void submit(Serializable[] ids) {
- Map map=new HashMap();
- map.put("state",1);//1启用
- map.put("ids", ids);
- exportDao.updateState(map);
- }
- @Override
- public void cancel(Serializable[] ids) {
- Map map=new HashMap();
- map.put("state",0);//0启用
- map.put("ids", ids);
- exportDao.updateState(map);
- }
- }
我们的update方法和插入方法后期还要继续完善,这里我们先简单的写一下。
然后使我们的Controller层:
- package cn.hpu.jk.controller.cargo.export;
- import java.util.List;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
- import cn.hpu.jk.controller.BaseController;
- import cn.hpu.jk.domain.Export;
- import cn.hpu.jk.service.ExportService;
- @Controller
- public class ExportController extends BaseController{
- @Autowired
- ExportService exportService;
- @RequestMapping("/cargo/export/list.action")
- public String list(Model model){
- List<Export> dataList=exportService.find(null);
- model.addAttribute("dataList", dataList);
- return "/cargo/export/jExportList.jsp";
- }
- }
我们在beans-service.xml中注入exportService:
- <bean name="exportService" class="cn.hpu.jk.service.impl.ExportServiceImpl"/>
我们这里先写一个获取出口报运信息列表的方法,然后我们写一个Jsp页面来显示出口报运信息列表:
jExportList.jsp:
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%@ include file="../../baselist.jsp"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- </head>
- <body>
- <form name="icform" method="post">
- <div id="menubar">
- <div id="middleMenubar">
- <div id="innerMenubar">
- <div id="navMenubar">
- <ul>
- <li id="view"><a href="#" onclick="formSubmit('toview.action','_self');this.blur();">查看</a></li>
- <li id="new"><a href="#" onclick="formSubmit('tocreate.action','_self');this.blur();">添加</a></li>
- <li id="update"><a href="#" onclick="formSubmit('toupdate.action','_self');this.blur();">修改</a></li>
- <li id="delete"><a href="#" onclick="formSubmit('delete.action','_self');this.blur();">删除</a></li>
- <li id="new"><a href="#" onclick="formSubmit('submit.action','_self');this.blur();">上报</a></li>
- <li id="new"><a href="#" onclick="formSubmit('cancel.action','_self');this.blur();">取消</a></li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- <!-- 页面主体部分(列表等) -->
- <div class="textbox" id="centerTextbox">
- <div class="textbox-header">
- <div class="textbox-inner-header">
- <div class="textbox-title">
- 出口报运列表
- </div>
- </div>
- </div>
- <div>
- <div class="eXtremeTable" >
- <table id="ec_table" class="tableRegion" width="98%" >
- <thead>
- <tr>
- <td class="tableHeader"><input type="checkbox" name="selid" onclick="checkAll('id',this)"></td>
- <td class="tableHeader">序号</td>
- <td class="tableHeader">合同或确认书号</td>
- <td class="tableHeader">信用证号</td>
- <td class="tableHeader">货物数/附件数</td>
- <td class="tableHeader">收货人及地址</td>
- <td class="tableHeader">装运港</td>
- <td class="tableHeader">目的港</td>
- <td class="tableHeader">运输方式</td>
- <td class="tableHeader">价格条件</td>
- <td class="tableHeader">制单日期</td>
- <td class="tableHeader">状态</td>
- </tr>
- </thead>
- <tbody class="tableBody" >
- <c:forEach items="${dataList}" var="o" varStatus="status">
- <tr class="odd" onmouseover="this.className='highlight'" onmouseout="this.className='odd'" >
- <td><input type="checkbox" name="id" value="${o.id}"/></td>
- <td>${status.index+1}</td>
- <td><a href="toview.action?id=${o.id}">${o.customerContract}</a></td>
- <td>${o.lcno}</td>
- <td>${o.epnum }/${o.extnum }</td>
- <td>${o.consignee}</td>
- <td>${o.shipmentPort}</td>
- <td>${o.destinationPort}</td>
- <td>${o.transportMode}</td>
- <td>${o.priceCondition}</td>
- <td><fmt:formatDate value="${o.inputDate}" pattern="yyyy-MM-dd"/></td>
- <td>${o.totalAmount}</td>
- <td>
- <c:if test="${o.state==1}"><font color="green">已上报</font></c:if>
- <c:if test="${o.state==0}">草稿</a></c:if>
- </td>
- </tr>
- </c:forEach>
- </tbody>
- </table>
- </div>
- </div>
- </form>
- </body>
- </html>
我们的数据入口,在left.jsp中添加“出口报运”的链接:
- <ul>
- <li><a href="${ctx }/cargo/contract/list.action" onclick="linkHighlighted(this)" target="main" id="aa_1">购销合同</a></li>
- <li><a href="${ctx }/cargo/outproduct/toedit.action" onclick="linkHighlighted(this)" target="main" id="aa_1">出货表</a></li>
- <li><a href="${ctx }/cargo/export/list.action" onclick="linkHighlighted(this)" target="main" id="aa_1">出口报运</a></li>
- </ul>
效果如:
我们先加一些测试数据,然后点击出口报运,获取列表:
至此我们的出口报运的增删改查的Mapper以及Dao还有Service以及Controller层的编写,list列表获取的方法。我们下一次开始编写出口报运的其他业务方法。