本人在编写一个软件,主要用于货物销售,采用struts架构,后台使用MS SQLSERVER。
我碰到的问题是:
一次销售可能包含多个产品,那么数据库设计采用主表-子表的形式,一对多关系。在jsp页面输入每个产品的销售数量时,可能会出现大于库存数量,或者无该产品库存(存储库存的表没有对应的记录),一旦碰上这种情况,我需要回滚本次销售发生的所有操作,包括库存数量足够的记录。我不知道该怎么处理,设置autocommit为false,在javabean里逐条写sql语句好像不可取,但数据库存储过程又无法传递数组参数(一次销售中产品种类的数量不确定,只能用数据等数据结构),该怎么处理好呢?我能想到的办法是:先把数据存到一张临时表,然后调用存储过程把数据存入正式表,在存储过程中启用事务处理,并使用
cursor逐条验证库存数量,一旦发现一条数量不足,回滚所有操作。但我觉得我这个方法挺笨的,请教高手,给一个好的方法。
我碰到的问题是:
一次销售可能包含多个产品,那么数据库设计采用主表-子表的形式,一对多关系。在jsp页面输入每个产品的销售数量时,可能会出现大于库存数量,或者无该产品库存(存储库存的表没有对应的记录),一旦碰上这种情况,我需要回滚本次销售发生的所有操作,包括库存数量足够的记录。我不知道该怎么处理,设置autocommit为false,在javabean里逐条写sql语句好像不可取,但数据库存储过程又无法传递数组参数(一次销售中产品种类的数量不确定,只能用数据等数据结构),该怎么处理好呢?我能想到的办法是:先把数据存到一张临时表,然后调用存储过程把数据存入正式表,在存储过程中启用事务处理,并使用
cursor逐条验证库存数量,一旦发现一条数量不足,回滚所有操作。但我觉得我这个方法挺笨的,请教高手,给一个好的方法。
解决方案 »
- HQL语句能写左外连接么????急求??
- 复选框中有全选的情况~~
- 如何使用Java将时间动态的显示在网页中
- 手机网页怎么做到像淘宝那样用uc适应屏幕和缩放排版时显示的都一样?
- 收藏 不显示删除回复显示所有回复显示星级回复显示得分回复 求助,部署在同一台机子上的不同服务如何实现权限控制和数据交互?
- 大家帮个忙哦 关于struts标签使用的问题
- 一个级联问题
- 请教我的servlet为什么不能跳转,从192.168.0.102/idc/login.htm中不能跳转到其他页面,显示结果为:Directory Listing For /login/ - Up
- 急!!jspsmartupload下载文件 路径设置问题
- 一个着急的小问题!!!servlet println返回的html标记中有"怎么办?
- jsp关于隐藏单元格的问题
- ant编译程序出错
如果是多个数据库,可以考虑JTA。
UserTransaction userTran;
try
{
userTran = UserTransactionManager.getUserTransaction();
}
catch (NamingException exp)
{
logger.error("UserTransaction init exception");
throw new BPServiceException("事务初始化异常",exp);
}try
{
userTran.begin(); // 启动事务// 这里是正常的业务逻辑 userTran.commit(); // 提交事务
}
catch (Exception exp)
{
try
{
userTran.rollback(); // 发生异常,回滚事务
}
catch (Exception exp1)
{
logger.error("UserTransaction rollback exception.", exp1);
}
}
如果用Spring的话,可以直接使用Spring的事务管理
我还想问问,你的代码里面的业务逻辑怎么写?是一条sql语句定义一个statement吗?那岂不是很复杂
然后再存储过程里面进行split ,
这个函数到处都是,在一sp里面处理的话,肯定可以事务同步了吧。
但是一个业务可能涉及多个DAO的操作,所以事务是要放在业务层的。上面那段代码是直接操作JTA的,如果你使用类似SSH这样的开发框架的话,不需要这么复杂,直接在Spring的配置文件配置,或是用Annotation就可以了。至于SQL的Statement,一个对象可以执行多个SQL。更主要的是简化同一段代码中的业务逻辑,而不是减少几个SQL语句。
UserTransaction是JTA中定义的接口,引用jta-1.0.jar就可以了。但是还需要一个JTA的实现,比如JOTM之类的。
如果不涉及到多个数据库操作的话,也可以直接用JDBC的事务,方法这上面的类似,只是方法名有点差异。
非常感谢老兄如此热心及时的回复。
我只用了struts,也没用过spring和hibernate。
你的回答我还是不太明白,能给例子吗?
以下是我写的存储过程,但只对单条数据操作
begin transaction
update depository set kcsl=kcsl-@ghsl where dm_ck=@dmck and dm_hw=@dmhw
if @@rowcount=0
begin
print 'no rows were updated'
rollback transaction
end
else
begin
select @result=kcsl from depository where dm_ck=@dmck and dm_hw=@dmhw
if @result<0
begin
print 'ghsl is more than kcsl'
rollback transaction
end
else
begin
insert into sellitem(dmck,dmhw,ghsl,ghje,mainid)values(@dmck,@dmhw,@ghsl,0,0)
print 'success'
commit transaction
end
end
我的业务逻辑虽然不复杂,主要就是去库存表里看看所要销售的货物是否存在,数量是否足够,一旦发现一条数量不足,回滚所有操作。但写成sql语句还是不少的,我估计只能在存储过程中实现。
但是,这样问题又回到最初,我如何把我的多条货物数据(每条记录至少有仓库代码,货物代码,销售数量,销售金额4个字段)传递给存储过程。如果数据能够到达存储过程,做事务处理肯定没问题的。所以我才采用临时表的解决办法。难道没有在Java中操作的更好的办法吗?顺便问一句,帖子回复时如何表示代码?
{
Connection conn = getConnection();
conn.setAutoCommit(false);
try
{
Statement stmt = conn.createStatement();
int count = stmt.executeUpdate("update....");
if(count == 0) throw new Exception();
ResultSet rs = stmt.executeQuery("select....");
if(rs.getInt("result") == 0)
throw new Exception();
stmt.execute("insert....");
conn.commit();
}catch(Exception exp){
conn.rollback();
}
}
如果需要多个产品处理的话,可以修改参数,改成List之类的。但是这段程序有个需要注意的地方是getConnection()的地方,使用之后要释放,然后如果传入List参数的话,不要每次都getConnection().