/*********************************************************************/
主从表事务控制解决方法EJB3.0
author:chinayaosir
QQ:44633197 QQ Group:8284865,34610648
blog http://blog.csdn.net/chinayaosir
0.事务一致性控制解释:
银行卡转帐操作事务:
用户从张三帐号1111222333444转帐8000.00到李四帐号2222333344445555!
步骤如下:
0.1验证张三密码和帐号正确!
0.2验证李四帐号2222333344445555输入正确!
0.3张三输入转帐金额8000.00!
0.4计算手续费4.00
0.5验证张三帐号余额>=8000.00+4.00
0.6李四帐号2222333344445555加上8000.00
0.7张三帐号1111222333444减去8004.00
0.8事务控制
0.6到0.7共2步没有任何错误,则转帐成功[提交事务]!
0.6到0.7共2步 有任何错误,则转帐失败[回滚事务]!
/*********************************************************************/
1.主表和从表事务控制要求
假设主表只有一行数据,而从表有1到n行数据!
当我们一起保存或者删除主表和从表,事务要求如下:
1.1.Create/Update事务要求
如果主表Create/Update失败而从表Create/Update成功;
或者主表Create/Update成功而从表Create/Update失败.
则整个事务都回滚,结果是主从表保存失败,达到事务控制要求.
打个比方:完成一件事情要经过A->B->C->D->E->F共6步,
如果6步中有一步出错, 则Create/Update成功的部分被事务回滚强制取消;
如果6步中没有一步出错,则mCreate/Update成功,则事务提交!
1.2.delete事务要求
如果主表delete失败而从表delete成功;
或者主表delete成功而从表delete失败.
则整个事务都回滚,结果是主从表delete失败,达到事务控制要求.
/*********************************************************************/
2.主表和从表事务控制EJB客户调用方法
2.1Create/update调用:spdaotrans.SaveWithTransation(sphead, splist);
sphead=主表,1行记录(最多只能输入一条)
splist=从表,2行记录(可以输入1-N条,N属于自然数)
2.2Delete调用:spdaotrans.DeleteWithTransation("PB100563");
"PB100563"=主从表都使用的一个关键字PK,
DeleteWithTransation()方法由1-2-3步删除数据构成一个整体事务!
2.3源码参考
package com;
//import java basic package
import java.util.*;
import java.lang.String;
import java.text.SimpleDateFormat;
import javax.naming.InitialContext;
//import entity and service package
import shipping.entity.*;
import shipping.shippingDAO.spDAOTransRemote;
public class testTransation {
public static void main(String[] args) {
//************************begin************************************
try {
//1.InitialContext and get spDAOTrans object
InitialContext ctx = JNDIContext.getInitContextByRemote();
spDAOTransRemote spdaotrans=(spDAOTransRemote)ctx.lookup("spDAOTrans/remote");
//************************************************************
//2.Save with transation test value=OK
//SaveWithTransation(SSpMaster m,List<SSpDetail> d )
System.out.println("SaveWithTransation(SSpMaster m,List<SSpDetail> d )");
System.out.println("fill SSpMaster data");
//2.1fill SSpMaster
SSpMaster sphead=new SSpMaster();
SSpMasterId spheadpk=new SSpMasterId();
spheadpk.setPsonumber("PB100563");
spheadpk.setSubcustom("0000000000");
String s1="10/29/2010",s2="10/25/2010",s3="10/30/2010";
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Date d1=sdf.parse(s1);
Date d2=sdf.parse(s2);
Date d3=sdf.parse(s3);
sphead.setId(spheadpk);
sphead.setPshipDate(d1);
sphead.setShippDate(d2);
sphead.setShip2Date(d3);
sphead.setCustomerid("B.A.B.");
sphead.setDestinatio("COLUMBUS, OHIO");
sphead.setCustofPoe("LONG BEACH");
sphead.setId(spheadpk);
//2.2fill SSpDetail list
System.out.println("fill SSpDetail data");
SSpDetailId spdetailpk1=new SSpDetailId();
SSpDetail spdetail1=new SSpDetail();
SSpDetailId spdetailpk2=new SSpDetailId();
SSpDetail spdetail2=new SSpDetail();
ArrayList<SSpDetail> splist = new ArrayList<SSpDetail>();
String sdate="10/25/2010";
SimpleDateFormat sdfDetail = new SimpleDateFormat("MM/dd/yyyy");
Date d_shipdate=sdfDetail.parse(sdate);
//2.3fill spdetailpk data
spdetailpk1.setShippDate(d_shipdate);
spdetailpk1.setPsonumber("PB100563");
spdetailpk1.setOcNumber("B1000577");
spdetailpk1.setItemnumber("BY34317");
spdetailpk1.setSubcustome("B.A.B./OH");
//2.4fill spdetail1 data
spdetail1.setId(spdetailpk1);
spdetail1.setCustomerid("B.A.B.");
spdetail1.setItemofname("C.P.O #");
spdetail1.setItemofpono("1006944");
spdetail1.setLoadofname("P.O.#");
spdetail1.setLoadofpono("1006944");
Long qty1=new Long(3708);
spdetail1.setLoadqtyinp(qty1);
spdetail1.setOrdercqty(qty1);
//2.5fill spdetail2 data
spdetailpk2.setShippDate(d_shipdate);
spdetailpk2.setPsonumber("PB100563");
spdetailpk2.setOcNumber("B1000578");
spdetailpk2.setItemnumber("BY34318");
spdetailpk2.setSubcustome("B.A.B./OH");
Long qty2=new Long(17208);
spdetail2.setId(spdetailpk2);
spdetail2.setLoadqtyinp(qty2);
spdetail2.setOrdercqty(qty2);
spdetail2.setCustomerid("B.A.B.");
spdetail2.setItemofname("C.P.O #");
spdetail2.setItemofpono("1006944");
spdetail2.setLoadofname("P.O.#");
spdetail2.setLoadofpono("1006944");
//2.5.add spdetail1,spdetail2 into splist
splist.add(spdetail1);//insert 1 row
splist.add(spdetail2);//insert 2 row
//2.6.主从表一起保存(包含对三个表的操作)
spdaotrans.SaveWithTransation(sphead, splist);
//************************************************************
//3.Delete with transation
//DeleteWithTransation(String sp)
System.out.println("DeleteWithTransation(sp)");
//主从表一起删除包含对三个表的操作
spdaotrans.DeleteWithTransation("PB100563");
//************************************************************
//4.spNumber Create,Retrieve,Update,Delete
//spNumber Create test value=>ok
System.out.println("getspNumber()");
spdaotrans.spNumberGet(); //create spnumber with database procedure
} catch (Exception e) {
e.printStackTrace();
}//end try
//************************end************************************
}//end main
}//end class
/*********************************************************************/
3.主表和从表事务控制EJB实现方法
EJB3.0事务控制标注:
3.1用@TransactionAttribute(NOT_SUPPORTED)标注整个类spDAOTrans不支持事务,代码如下:
@TransactionAttribute(NOT_SUPPORTED)
public class spDAOTrans implements spDAOTransRemote
3.2用@TransactionAttribute(REQUIRED)标注save方法支持事务,代码如下:
@TransactionAttribute
public void SaveWithTransation(SSpMaster m,List<SSpDetail> d )
3.3用@TransactionAttribute(REQUIRED)标注delete方法支持事务,代码如下:
@TransactionAttribute(REQUIRED)
public void DeleteWithTransation(String sp)
3.4完整源码如下!
package shipping.shippingDAO;
//import java basic package
import java.util.Date;
import java.util.Iterator;
import java.util.List;
//import ejb3.0
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import static javax.ejb.TransactionAttributeType.*;
//import entity and util package
import shipping.entity.*;
import publicUtility.LogUtil;
import java.util.logging.Level;
@Stateless
@TransactionAttribute(NOT_SUPPORTED)
public class spDAOTrans implements spDAOTransRemote {
@PersistenceContext
private EntityManager em;
@TransactionAttribute(REQUIRED)
public void SaveWithTransation(SSpMaster m,List<SSpDetail> d ){
try{
String sp=m.getId().getPsonumber();
spMasterSave(m); //1.save master
spDetailDelete(sp); //2.delete history data
Iterator isp = d.iterator(); //3.save detail list
while(isp.hasNext()){
SSpDetail echo_d = (SSpDetail)isp.next();
spDetailSave(echo_d);
}
spNumberChgFlag(sp,"1"); //4.update psnumber flag
}catch(Exception e){
System.out.println("Transation fail!");
}
}
@TransactionAttribute(REQUIRED)
public void DeleteWithTransation(String sp){
try{
spMasterDelete(sp); //1.delete master
spDetailDelete(sp); //2.delete detail
spNumberChgFlag(sp,"0"); //3.update spnumber flag
}catch(Exception e){
System.out.println("Transation fail!");
}
}
//SpMaster save,delete,find
//SpMaster save
private void spMasterSave(SSpMaster entity) {
LogUtil.log(" spMasterSave(SSpMaster entity)" , Level.INFO,null);
try {
SSpMasterId id=new SSpMasterId();
id.setPsonumber(entity.getId().getPsonumber());
id.setSubcustom(entity.getId().getSubcustom());
SSpMaster instance = em.find(SSpMaster.class, id);
if (instance!=null){//存在则修改
instance.setBlSooffcr(entity.getBlSooffcr());
instance.setBoatclose(entity.getBoatclose());
instance.setCustofPoe(entity.getCustofPoe());
instance.setCustomerid(entity.getCustomerid());
instance.setDestinatio(entity.getDestinatio());
instance.setRevisedate(entity.getRevisedate());
instance.setPshipDate(entity.getPshipDate());
instance.setShip2Date(entity.getShip2Date());
instance.setShippDate(entity.getShippDate());
instance.setSopsoFlag(entity.getSopsoFlag());
em.merge(instance);
}
else{//不存在则插入
em.persist(entity);
}
} catch (RuntimeException re) {
LogUtil.log("spMasterSave() failed", Level.SEVERE, re);
throw re;
}
}
//SpMaster delete
private void spMasterDelete(String sp) {
LogUtil.log("spMasterDelete(String sp)" , Level.INFO,null);
try {
Query query=em.createQuery("DELETE FROM SSpMaster c WHERE c.id.psonumber=:sp");
query.setParameter("sp",sp);
query.executeUpdate();
} catch (RuntimeException re) {
LogUtil.log("spMasterDelete() failed", Level.SEVERE, re);
throw re;
}
}
//SpDetail save,delete,find
//SpDetail save
private void spDetailSave(SSpDetail entity) {
LogUtil.log("void spDetailSave(SSpDetail entity)" , Level.INFO,null);
try {
SSpDetailId id=new SSpDetailId();
id.setItemnumber(entity.getId().getItemnumber());
id.setOcNumber(entity.getId().getOcNumber());
id.setPsonumber(entity.getId().getPsonumber());
id.setShippDate(entity.getId().getShippDate());
id.setSubcustome(entity.getId().getSubcustome());
SSpDetail instance = em.find(SSpDetail.class, id);
if (instance!=null){//存在则修改
instance.setCustomcode(entity.getCustomcode());
instance.setCustomerid(entity.getCustomerid()) ;
instance.setItemofname(entity.getItemofname());
instance.setItemofpono(entity.getItemofpono());
instance.setLoadofname(entity.getLoadofname());
instance.setLoadofpono(entity.getLoadofpono());
instance.setLoadqtyinp(entity.getLoadqtyinp());
instance.setOrdercqty(entity.getOrdercqty());
instance.setSopsoFlag(entity.getSopsoFlag());
em.merge(instance);
}
else{//不存在则插入
em.persist(entity);
}
} catch (RuntimeException re) {
LogUtil.log("spDetailSave() failed", Level.SEVERE, re);
throw re;
}
}
//SpDetail delete
private void spDetailDelete(String sp) {
LogUtil.log("spDetailDelete(String sp) " , Level.INFO,null);
try {
Query query=em.createQuery("delete from SSpDetail where psonumber=:sp");
query.setParameter("sp",sp);
query.executeUpdate();
} catch (RuntimeException re) {
LogUtil.log("spDetailDelete() failed", Level.SEVERE, re);
throw re;
}
}
//spNumber create,update,find
//spNumber create
@TransactionAttribute(REQUIRED)
public void spNumberGet() {
LogUtil.log("void spNumberGet()", Level.INFO,null);
try {
Query query=em.createNativeQuery("{call get_sp_number()}");
query.executeUpdate();
}
catch (RuntimeException re) {
LogUtil.log("spNumberGet() failed", Level.SEVERE, re);
throw re;
}
}
//spNumber update
private void spNumberChgFlag(String sp, String flag) {
LogUtil.log("spNumberChgFlag(String sp,String flag)", Level.INFO,null);
try {
Query query=em.createQuery("UPDATE SSpNumber c " +
"SET c.flag=:flag WHERE c.psonumber=:sp");
query.setParameter("flag",flag);
query.setParameter("sp",sp);
query.executeUpdate();
} catch (RuntimeException re) {
LogUtil.log("spNumberChgFlag() failed", Level.SEVERE, re);
throw re;
}
}
}