Spring和Ibatis的实例

    结合于Spring和Ibatis的实际运用我写了一个例子,例子中实现了一个简单的登录过程和一个订货单的主从表形式的增、删、改、查功能,以供大家参考。

       我使用了Spring中的AbstractController控制器作为整个程序的基本的控制器,之所以这样做是考虑到简单实用的目的,同时能够实现主从表形式的数据输入,对于事务管理直接用ibatis中提供的事务管理功能,jsp页面统一存放在WEB-INF\view\下面,这样可以防止用户直接通过地址栏来访问jsp页面,jsp页面上用到的js脚本都以js文件的形式include到页面中,对于页面上的数据都以jstl的标签来输出达到页面简洁的目的。

配置文件说明

/WEB-INF/web.xml文件

程序运行的主要配置文件,配置了各种系统变量,对spring的加载,日志的加载等等

   

/WEB-INF/applicationContext.xml文件

启动时由spring加载系统中用到的各种bean

   

/WEB-INF/main-config.xml文件

对系统管理模块中的请求/处理单元的配置

   

/WEB-INF/indent-config.xml文件

对订货单模块中的请求/处理单元的配置

   

/WEB-INF/sqlMapConfig.xml文件

Ibatis的核心配置文件

   

WEB-INF\classes\com\ user.xml文件

用户模块的sql语句的映射文件

   

WEB-INF\classes\com\ common.xml文件

公用模块的sql语句的映射文件

   

WEB-INF\classes\com\ indent.xml文件

订货单模块的映射文件

   

对于系统中用到的控制器,我首先对AbstractController进行了抽象,编写了SimpleController类,在SimpleController类中我加入了各控制器中都要用到的公用属性和公用的bean,并抽象出AbstractController

public abstract ModelAndView handleRequestInternal(HttpServletRequest request,

                                            HttpServletResponse response) throws Exception;方法

其它各模块则继承自SimpleController,实现该方法,这样就可以使用SimpleController类中的各种属性和方法。

   

程序运行的具体流程如下

首先访问站点的入口web/index.jsp文件

<%@ include file="/WEB-INF/view/inc/head.jsp" %>

<%-- Redirected because we can't set the welcome page to a virtual URL. --%>

   

<c:redirect url="/loginInit.do"/>

文件中首先include了对jstl标签库的引用/WEB-INF/view/inc/head.jsp文件

<%@ page session="true"%>

<%@ taglib prefix="spring" uri="/WEB-INF/spring.tld"%>

<%@ taglib prefix="c"   uri="/WEB-INF/c.tld" %>

<%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>

   

<c:redirect url="/loginInit.do"/>标签是重定向标签,该标签发出请求动作/loginInit.doweb容器,web容器依据web.xml中定义的请求映射动作

  <servlet-mapping>

    <servlet-name>main</servlet-name>

    <url-pattern>*.do</url-pattern>

  </servlet-mapping>

将该动作交由main所定义的系统管理模块的引擎进行调度

<servlet>

    <servlet-name>main</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>

      <param-name>contextConfigLocation</param-name>

      <param-value>/WEB-INF/main-config.xml</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

  </servlet>

该引擎接收到请求动作后,将该动作分发至系统管理逻辑处理单元就是/WEB-INF/main-config.xml文件

  <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

    <property name="mappings">

      <props>

        <prop key="/loginInit.do">loginController</prop>

        <prop key="/loginSubmit.do">loginController</prop>

      </props>

    </property>

  </bean>

main-config.xml文件通过urlMapping中定义的请求动作与控制器的映射

<prop key="/loginInit.do">loginController</prop>

将动作交由loginController所定义的控制器处理

  <bean id="loginController" class="com.manage.LoginController">

    <property name="bean"><ref bean="bean"/></property>

    <property name="sqlMap"><ref bean="sqlMap"/></property>

    <property name="formView"><value>login</value></property>

    <property name="successView"><value>main</value></property>

    <property name="mainField">

      <list>

        <value>usercode</value>

        <value>password</value>

      </list>

    </property>

  </bean>

该控制器引用了applicationContext.xml文件中加载的bean和sqlMap实例

<property name="bean"><ref bean="bean"/></property>

<property name="sqlMap"><ref bean="sqlMap"/></property>

以及对控制器处理请求后返回的视图属性的定义

<property name="formView"><value>login</value></property>

<property name="successView"><value>main</value></property>

com.manage.LoginController控制器主要实现了

  public ModelAndView handleRequestInternal(HttpServletRequest request,

                                    HttpServletResponse response) throws Exception 方法,该方法主要是对请求动作进行处理并返回一个ModelAndView对象,ModelAndView类包含了逻辑单元返回的结果数据集和表现层信息

  public ModelAndView handleRequestInternal(HttpServletRequest request,

                                    HttpServletResponse response) throws Exception {

   

    log.info(request.getMethod());

    Map model = new HashMap();

    Map userForm =null;

    Map userInfo = null;

   

    if(isGet(request)){

      userForm =  new HashMap();

      userForm.put("usercode","A1118");

      userForm.put("password","123");

      model.put("userForm",userForm);

      return new ModelAndView(formView,model);

    }

    else{

      userForm = (Map)bean.fillMap(mainField, request);

      try{

        sqlMap.startTransaction();

        userInfo = (Map)sqlMap.queryForObject("user.selectUser", userForm.get("usercode"));

        sqlMap.commitTransaction();

      }

      finally{

        sqlMap.endTransaction();

      }

      if(userInfo == null){

        model.put("message", "没有找到该用户");

        model.put("userForm", userForm);

        returnView = formView;

      }

      else{

        model.put("message", "登录成功");

        model.put("userInfo", userInfo);

        returnView = successView;

        printMap(userInfo);

        request.getSession().setAttribute("userInfo", userInfo);

      }

      return new ModelAndView(returnView, model);

    }

  }

这里我是用一个控制器对登录的初始化动作和登录提交动作进行控制,通过

if(isGet(request))来区分,初始化动作中将用户信息封装在model中并通过

return new ModelAndView(formView,model);

formView是请求动作返回的视图,在配置文件中已经定义了

<property name="formView"><value>login</value></property>

model是返回的结果数据集

将返回的视图和数据集交由urlMapping,urlMapping会根据applicationContext.xml中定义的

  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>

    <property name="prefix"><value>/WEB-INF/view/</value></property>

    <property name="suffix"><value>.jsp</value></property>

  </bean>

  

viewResolver在返回的视图的字符串加上前缀/WEB-INF/view/和后缀.jsp,即

/WEB-INF/view/login.jsp

然后通过main的调度引擎返回到login页面

<%@ page contentType="text/html; charset=GBK" %>

<%@ include file="/WEB-INF/view/inc/head.jsp" %>

<html>

<head>

<title>

login

</title>

<%@ include file="/WEB-INF/view/inc/css-js.inc" %>

</head>

<body bgcolor="#ffffff">

<spring:message code="title"/>

<spring:message code="fff"/>

   

<form action="/loginSubmit.do" method="POST">

<table width="100%" height="100%">

  <tr>

    <td  align="center" valign="middle">

      <c:if test="${message!=null}">

        <h4><c:out value="${message}" /></h4><br>

      </c:if>

  用户编号:<input type="text" name="usercode" value="<c:out value="${userForm.usercode}"/>"/>

  <br/>

  用户密码:<input type="text" name="password" value="<c:out value="${userForm.password}"/>"/>

   <br/> <input type="submit" value="ok"/>

    </td>

  </tr>

</table>

</form>

</body>

</html>

Login页面上使用了jstl的标签进行输出。这样一个登录初始化的过程就完成,

登录提交的原理和登录初始化的运行原理一样,

在登录提交过程中我也是使用的com.manage.LoginController控制器,在提交过程中我通过

userForm = (Map)bean.fillMap(mainField, request);方式将页面提交过来的表单数据封装在

userForm中的(订货单模块中都是用bean.fillMap和bean.fillMaps来封装请求参数的),,这里的mainField是一个字符串数组,由LoginController的父类SimpleController中定义,bean也是在SimpleController定义的

mainField的作用是设置表单提交过来的字段,通过在配置文件中定义,这样可以避免硬编码,

    <property name="mainField">

      <list>

        <value>usercode</value>

        <value>password</value>

      </list>

    </property>

Bean的作用是将请求的表单中的数据以key和value 形式封装在Map中

在提交过程中我使用了ibatis中的核心组件sqlMap,也是在配置文件中定义的

<property name="sqlMap"><ref bean="sqlMap"/></property>

Sqlap的调用方法如下

      try{

        sqlMap.startTransaction();开启事务

        userInfo = (Map)sqlMap.queryForObject("user.selectUser", userForm.get("usercode"));

        sqlMap.commitTransaction();提交事务

      }

      finally{

        sqlMap.endTransaction();结束事务

      }

(Map)sqlMap.queryForObject("user.selectUser", userForm.get("usercode"));方法用于查询用户的信息,"

user.selectUser"是对应于user.xml映射文件中的selectUsersql语句的映射,userForm.get("usercode")是输入的参数

  <select id="selectUser" parameterClass="java.lang.String" resultClass="java.util.HashMap">

    <![CDATA[

    select * from v_BsUserRole where userCode = #userCode#

    ]]>

  </select>

Id就是调用sql的引用名,

parameterClass是输入的参数

resultClass是返回的结果集封装的类

sqlMap.queryForObject会根据输入的sql的引用名来完成查询和数据封装工作,

如果找到记录,则封装在resultClass定义的对象中返回,没有找到则返回null

执行完毕后,LoginController会返回main页面或login页面。

整个程序中运行的流程大致相同,下面将对ibatis的使用进行说明

示例中我使用了以下几种查询和数据库的操作

   

?         查询订货单记录

查询单条记录在订货单修改时用到,类为

com.indent.IndentModController

订货单是主从表关系,因此需要配置主表查询语句和从表查询语句

sql的映射文件为indent.xml文件

<select id="getIndent" parameterClass="java.lang.String" resultClass="java.util.HashMap">

  <![CDATA[

    select sellID, sellIDShow, dealerCode, dealerName, orderCode, orderName, orderDate,

    sumSellNum, sumFeeSell, source, sourceExplain, status, statusExplain,remark

    from V_OS_Sell where sellID = #sellID#

  ]]>

</select>

<select id="getIndentList" parameterClass="java.lang.String" resultClass="java.util.HashMap">

  <![CDATA[

    select partCode, partName, unit, priceSell, numStorage, orderNum, orderSum

    from V_OS_SellList where sellID = #sellID#

  ]]>

</select>

Id:程序中对sql的引用名

parameterClass:输入参数,

resultClass:封装每条记录的类

对于查询一条记录时ibatis直接返回resultClass中定义的封装数据的对象

对于查询多条记录,ibatis会将每条记录封装在resultClass定义的对象实例中然后将所有这所对象封装在List中返回

    Map indent = null;

    List indentList = null;

    try{

      sqlMap.startTransaction();

      indent=(Map)sqlMap.queryForObject("indent.getIndent",sellID);订货单主表记录

      indentList = sqlMap.queryForList("indent.getIndentList",sellID);订货单从表记录

      sqlMap.commitTransaction();

    }

    finally{

      sqlMap.endTransaction();

    }

   

?         动态条件查询

动态条件查询是指通过查询页面提交的动态条件来组合不同的sql语句

我们以前是通过

String sql ="select * from table where bh='dd'"

If(request. getParameter("par")!=null&& request. getParameter("par"). length()>0){

  sql += " and field = '"+ request. getParameter("par")+"'";

}

…….

这种方式来组合的

考虑到这个问题,ibatis引入了动态映射机制

在订货单查询就用到了这种动态条件查询,对应的类是com.indent.IndentQueryController

首先我通过

indentForm = (Map)bean.fillMap(mainField, request);方法将查询条件封装在Map

然后将这个查询条件的对象交给sqlMap查询

partCount = ((Integer) sqlMap.queryForObject("indent.getIndentQueryCount", indentForm)).intValue();获得了查询的记录数

indentList=sqlMap.queryForList("indent.getIndentQuery", indentForm, skipResult, PAGE_SIZE);获得了分页的记录集

sql映射是

<select id="getIndentQueryCount" parameterClass="java.util.Map" resultClass="java.lang.Integer">

  <![CDATA[

    select count(sellID) from os_sell

    where (depotCode = #depotCode#) and (oldSellID is null) and (status='1')

  ]]>

  <dynamic prepend="AND">

    <isNotEmpty prepend="AND" property="sellID">

      <![CDATA[(sellID like '%'+#sellID#+'%')]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="dealerName">

      <![CDATA[(dealerName like '%'+#dealerName#+'%')]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderCode">

      <![CDATA[(orderCode = #orderCode#)]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderDate1">

      <![CDATA[(orderDate >= #orderDate1#)]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderDate2">

      <![CDATA[(orderDate <= #orderDate2#)]]>

    </isNotEmpty>

  </dynamic>

</select>

   

   

<select id="getIndentQuery" parameterClass="java.util.Map" resultClass="java.util.HashMap">

  <![CDATA[

    select sellID, sellIDShow, dealerName, sumSellNum, sumFeeSell,

    orderName, orderDate, sourceExplain from V_OS_Sell

    where (depotCode = #depotCode#) and (oldSellID is null) and (status='1')

  ]]>

  <dynamic prepend="AND">

    <isNotEmpty prepend="AND" property="sellID">

      <![CDATA[(sellID like '%'+#sellID#+'%')]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="dealerName">

      <![CDATA[(dealerName like '%'+#dealerName#+'%')]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderCode">

      <![CDATA[(orderCode = #orderCode#)]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderDate1">

      <![CDATA[(orderDate >= #orderDate1#)]]>

    </isNotEmpty>

    <isNotEmpty prepend="AND" property="orderDate2">

      <![CDATA[(orderDate <= #orderDate2#)]]>

    </isNotEmpty>

  </dynamic>

  <![CDATA[

  order by orderDate desc, sellID desc

  ]]>

</select>

   

对于动态映射的配置,大家可以看<ibatis开发指南>31-34页里面讲得很清楚

   

?         操作语句

操作语句包括订货单的插,改,删

这里只说一下订货单的插入过程,类是com.indent.IndentAddSaveController

首先IndentAddSaveController在获得提交保存的请求后,将订货单主表信息封装在map,从表信息封装在list

    Map indent = (Map)bean.fillMap(mainField,request);

    List indentList = bean.fillMaps(childField,request);

然后通过事务管理,插入订货单主表信息,循环插入订货单子表信息

    try{

      sqlMap.startTransaction();

      sqlMap.insert("indent.insertIndent",indent);

      for (int i = 0; i < indentList.size(); i++) {

        indentPart = (Map)indentList.get(i) ;

        indentPart.put("sellID",sellID);

        sqlMap.insert("indent.insertIndentList",indentPart);

      }

      sqlMap.commitTransaction();

    }

    finally{

      sqlMap.endTransaction();

    }

对应的sql配置是

<insert id="insertIndent" parameterClass="java.util.Map">

   <![CDATA[

    insert into OS_Sell

    (sellID,dealerCode,dealerName,depotCode,orderCode,orderDate,

    sumSellNum,sumFeeSell,source,status,remark,isBack)

    values(#sellID#,#dealerCode#,#dealerName#,#depotCode#,#orderCode#,#orderDate#,

    #sumSellNum#,#sumFeeSell#,#source#,'1',#remark#,'2');

   ]]>

</insert>

   

<insert id="insertIndentList" parameterClass="java.util.Map">

   <![CDATA[

    insert into OS_SellList

    (sellID, partCode, partName, unit, priceSell, orderNum)

    values

    (#sellID#, #partCode#, #partName#, #unit#, #priceSell#, #orderNum#)

   ]]>

</insert>

   

?         调用存储过程

存储过程的调用在订货单新建过程中用到,订货单新建时首先要获得一个唯一的ID

对应的类是com.indent. IndentAddController

       首先我将存储过程需要用到的参数封装在map中,提交给sqlMap执行存储过程

       Map parMap = null;

    try {

      sqlMap.startTransaction();

      parMap = new HashMap();

      parMap.put("type","X");

      parMap.put("depot","A1118");

      parMap.put("code",null);

      sqlMap.update("common.getCode",parMap);

      sqlMap.commitTransaction();

    }

    finally {

      sqlMap.endTransaction();

    }

    String sellID=(String)parMap.get("code");

   

       SqlMap会根据common.getCode所定的parameterMap

<parameterMap id="getCodeParameters" class="java.util.Map" >

  <parameter property="type" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN" />

  <parameter property="depot" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>

  <parameter property="code" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT" nullValue=""/>

</parameterMap>

   

<procedure id="getCode" parameterMap="getCodeParameters">

  <![CDATA[

  {call ProcGetMaxId(?,?,?)}

  ]]>

</procedure>

的输入输出参数来定义存储过程中的参数

这里我将code这个字段定义为OUT型,那么存储过程执行后会将返回的唯一的ID号存储在code中,在程序中就通过

String sellID=(String)parMap.get("code");可以得到了。

   

?         注意一点

sqlMap的执行默认情况下是自动提交的,在没有用

try {

  sqlMap.startTransaction();

  ………..

  sqlMap.commitTransaction();

    finally {

      sqlMap.endTransaction();

    }

进行事务管理时

每执行一个更新,查询,等数据访问方法时都会打开,和关闭一次连接,

因此,在一个动作中多次调用sqlMap的数据访问方法时都应该用事务来管理,不管是查询,还是更新。

   

spring开发指南》中需要重点看的章节

?         Spring Bean封装机制 19-28页 要会配置Bean

?         Spring 高级特性 29-64页 要明白其中的登录例子的流程

   

ibatis开发指南》中需要重点看的章节

?         ibatis配置 11-16页

?         SqlMapClient基本操作示例 16-17页 例1-例6

?         OR 映射 19-25页

?         动态映射 31-34页

?         事务管理-基于JDBC的事务管理机制 35-36页

   

   

附:

表结构

BS订货单主表

CREATE TABLE [dbo].[OS_Sell] (

       [SellID] [nvarchar] (17) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [DealerCode] [nvarchar] (6) COLLATE Chinese_PRC_CI_AS NULL ,

       [DealerName] [nvarchar] (60) COLLATE Chinese_PRC_CI_AS NULL ,

       [DepotCode] [nvarchar] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [StockID] [nvarchar] (17) COLLATE Chinese_PRC_CI_AS NULL ,

       [OrderCode] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NULL ,

       [OrderDate] [datetime] NULL ,

       [SumSellNum] [numeric](9, 1) NULL ,

       [SumFeeSell] [numeric](10, 2) NULL ,

       [ChangeCode] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NULL ,

       [ChangeDate] [datetime] NULL ,

       [AuditCode] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NULL ,

       [AuditDate] [datetime] NULL ,

       [OutCode] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NULL ,

       [OutDate] [datetime] NULL ,

       [Source] [char] (1) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [Status] [char] (1) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [Remark] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,

       [IsBack] [char] (1) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [OldSellID] [nvarchar] (17) COLLATE Chinese_PRC_CI_AS NULL ,

       [BackStatus] [nvarchar] (1) COLLATE Chinese_PRC_CI_AS NULL ,

       [InvoiceCode] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NULL ,

       [InvoiceNO] [nvarchar] (10) COLLATE Chinese_PRC_CI_AS NULL ,

       [InvoiceDate] [datetime] NULL

) ON [PRIMARY]

   

BS订货单从表

CREATE TABLE [dbo].[OS_SellList] (

       [SellID] [nvarchar] (17) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [PartCode] [nvarchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [PartName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

       [Unit] [nvarchar] (4) COLLATE Chinese_PRC_CI_AS NULL ,

       [PriceSell] [numeric](8, 2) NULL ,

       [OrderNum] [numeric](9, 1) NULL ,

       [OutNum] [numeric](9, 1) NULL ,

       [BackNum] [numeric](9, 1) NULL

) ON [PRIMARY]

   

总部库存表

CREATE TABLE [dbo].[O_Storage] (

       [DepotCode] [nvarchar] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [PartCode] [nvarchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [PartName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

       [Unit] [nvarchar] (4) COLLATE Chinese_PRC_CI_AS NULL ,

       [ProviderCode] [nvarchar] (4) COLLATE Chinese_PRC_CI_AS NULL ,

       [NumStorage] [numeric](9, 1) NULL ,

       [NumFreeze] [numeric](9, 1) NULL ,

       [PriceCost] [numeric](8, 2) NULL ,

       [PricePact] [numeric](8, 2) NULL ,

       [PriceMove] [numeric](8, 2) NULL ,

       [PriceStatus] [char] (1) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [StorageCode] [nvarchar] (14) COLLATE Chinese_PRC_CI_AS NULL

) ON [PRIMARY]

   

视图

--BS中的用户角色视图

--姜敏

CREATE       view v_BsUserRole

as

select

a.dealerCode,--经销商编号

a.areaCode,--区域编号

a.dealerName,--经销商名称

a.depotName,--仓库名称

a.kind,--等级分类

a.status as dealerStatus,--经销商状态

a.upDealerCode,--上级经销商代码

b.userCode,--用户代码

b.userName,--用户姓名

LOWER(b.password) as password ,--用户密码

b.lindType,--联系方式

b.status as userStatus,--用户状态

b.isAdmin,--是否管理员

c.roleCode,--角色编号

c.roleName--角色名称

   

from

p_dealer a

inner join p_user b on a.dealercode=b.depotcode

left outer join

  (select a.roleCode, a.roleName, b.userCode

   from r_bsRole a inner join r_bsRoleUser b on a.RoleCode = b.RoleCode) c

on b.userCode=c.userCode

   

   

订货单主表视图

CREATE  VIEW dbo.V_OS_Sell

AS

SELECT a.sellID, right(a.sellID,10) as sellIDShow, a.dealerCode, a.dealerName, f.areaCode, f.areaName, a.depotCode,

      h.dealerName AS depotName, a.stockID, a.orderCode, b.userName AS orderName,

      CONVERT(char(10), a.orderDate, 120) AS orderDate, cast(a.sumSellNum AS int)

      AS sumSellNum, a.sumFeeSell, a.changeCode, g.userName AS changeName,

      CONVERT(char(10), a.changeDate, 120) AS changeDate, a.auditCode,

      c.userName AS auditName, CONVERT(char(10), a.auditDate, 120) AS auditDate,

      a.outCode, d .userName AS outName, CONVERT(char(10), a.outDate, 120) AS outDate,

      a.source, (CASE a.source WHEN '1' THEN '转单' WHEN '2' THEN '自制' END)

      AS sourceExplain, a.status,

      (CASE a.status WHEN '1' THEN '已订货' WHEN '2' THEN '已转单' WHEN '3' THEN '已审核'

       WHEN '4' THEN '已出库' WHEN '5' THEN '已发运' WHEN ' 6 ' THEN '已确认' END)

      AS statusExplain, a.remark, a.isBack,

      (CASE a.isBack WHEN '1' THEN '' WHEN '2' THEN '' END) AS isBackExplain,

      a.oldSellID, a.backStatus,

      (CASE a.backStatus WHEN '1' THEN '未审核' WHEN '2' THEN '已审核' WHEN '3' THEN '已退货'

       END) AS backStatusExplain

FROM OS_Sell a INNER JOIN

      P_User b ON a.orderCode = b.userCode INNER JOIN

      P_Dealer e ON a.dealerCode = e.dealerCode INNER JOIN

      P_Dealer h ON a.depotCode = h.dealerCode LEFT OUTER JOIN

      P_Area f ON e.AreaCode = f.AreaCode LEFT OUTER JOIN

      P_User c ON a.auditCode = c.userCode LEFT OUTER JOIN

      P_User d ON a.outCode = d .userCode LEFT OUTER JOIN

      P_User g ON a.changeCode = g.userCode

  

   

订货单从表视图

/*

平台销售单子表

姜敏

*/

CREATE           view V_OS_SellList

as

   

select

a.sellID, --销售单ID

a.partCode, --零件号

a.partName, --零件名称

a.unit, --计量单位

a.priceSell, --销售价(合同成本价)

isnull((select top 1 pricePact from o_storage where depotCode='000001' and partCode = a.partCode),0) as factPrice,--当前的总部的销售价

cast(isnull((select top 1 numStorage from o_storage where depotCode = '000001' and partcode = a.partcode),0) as int) as numStorage,  --当前库存数量

cast(a.orderNum as int) as orderNum, --订货数量

a.priceSell*orderNum as orderSum, --订货金额

cast(a.outNum as int) as outNum, --出库数量

a.priceSell*outNum as outSum, --出库金额

cast(a.backNum as int) as backNum, --累计退票数量

a.priceSell*backNum as backSum, --累计退票金额

cast((a.orderNum+a.backNum) as int) as canBackNum, --可退数量

(a.orderNum+a.backNum)*a.priceSell as canBackSum--可退金额

   

from

OS_SellList a

inner join OS_Sell b on a.sellID = b.sellID

  

   

存储过程

--取单据号的存储过程--

CREATE    PROCEDURE ProcGetMaxId

@LX char(1),@CK nvarchar(6),@Code nvarchar(17) output

AS

Declare @i bigint,@No Varchar(11)

begin tran

Select @i=count(*) from P_MaxId where  (Code = @LX) and (DepotCode=@CK)

if @i>0

begin

  set @i=0

  Select @i=IDNO

  FROM P_MaxId

  WHERE (CONVERT(Varchar, CurrDate, 1) = CONVERT(Varchar, GETDATE(), 1))   AND

        (Code = @LX) and (DepotCode=@CK)

  if @i=0

  begin

     Set @No=Convert(Varchar,Getdate(),112)+'001'

     Update P_MaxId Set CurrDate=GetDate(),IDNO=Convert(bigint,@No) where  (Code = @LX) and (DepotCode=@CK)

  end

  else

  begin

    Update P_MaxId Set CurrDate=GetDate(),IDNO=IDNO+1 where  (Code = @LX) and (DepotCode=@CK)

  end

   Select @No=Convert(varchar,IDNO) from P_MaxId where (Code = @LX) and (DepotCode=@CK)

end

else

begin

     Set @No=Convert(Varchar,Getdate(),112)+'001'

     Insert P_MaxId(Code,DepotCode,CurrDate,IDNO) Values( @LX,@CK,GetDate(),Convert(bigint,@No) )

end

commit tran

set @Code= @CK+'_'+@LX+subString(@No,3,9)

--return 1

   

GO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值