事务管理核心:
当需要同时更改几个数据库表,比如购物车点击提交订单需要同时更改:订单详情表、订单追踪表、订单信息表。要改的话就需要三个表都改,要不改就同时都不改。当一个表更改失败,另外两个表也不能更改。
要实现这功能,就需要有一个WorkManager 类,同时对三个表更改,而且,需要把JDBC里的BaseDAO里的conn从workManager里传进去,需要保证对三个不同的子DAO用的是同一个connection。然后更改connection的提交方式为手动提交,当三个子DAO都完成操作,再用connection手动提交更改,这样就确保用的是同一个connection了。
pubulic class WorkManager(){
//这里的List<GoodsDetails> car 里的每一个元素,是产生不同订单明细的根源,因为一个订单可能有多个订单明细。所以传入car
public void orderWork(OrderInfo or,List<GoodsDetails> car,Orderzz ordzz){
//这里的用这个BaseDAO.URL,BaseDAO.USERNAME,BaseDAO.USERPWD是确保BaseDAO已经初始化,并且已经加载驱动
Connection conn = DriverManager.getConnection(BaseDAO.URL,BaseDAO.USERNAME,BaseDAO.USERPWD);
try{
//记录原先的connection的提交方式,并在完成事物管理后,更改回以前的状态
boolean flag = conn.getAutoCommit();
//更改conn的提交方式为手动提交
conn.setAutoCommit(flase);
new OrderInfoDAO(conn).insertOrder(ord);
new OrderzzDAO(conn).insertOrderzz(ordzz);
//用car里面的元素产生订单明细,并调用subDAO来操作数据库
for(int i=0;i<car.size();i++){
String g_id = car.get(i).getGs.getGood_id;
String count = car.get(i).getCount;
//调用工具类产生ordermxid
String ordermx_id = new createId.createOrdermxId;
String order_id = ord.getOrderId;
Ordermx ordmx = new Ordermx(ordermx_id,order_id,g_id,count);
new OrdermxDAO(conn).insertOrdermx(ordmx);
}
//connection手动提交
conn.Commit();
//更改为原先的提交方式
conn.setCommit(flag);
}catch(exception e){
try{
//当抓取到错误的时候,回滚操作,保证所有的数据库都没有被更改
conn.rollback;
}catch{
//回滚失败
}
}
}
}
注:1、需要更改JDBC BaseDAO里的构造函数。添加一个有参构造器public BaseDAO(Connection conn){ this.conn = conn};
并在无参构造器里产生conn。以保证不管是调用有参还是无参的构造器,都能正常的使用
2、资源关闭,原先的BaseDAO每当完成一次操作,就会关闭资源,但是在事物管理中,需要让在所有需要更改数据库完成之后,才能关闭资源。
回顾: JDBC 步骤:
1、加载驱动:
Class.forName("com.microsoft.sqlsever.jdbc.SQLServerDriver");
2、连接数据库:
Connection conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=shopping","sa","123");
3、创建命令执行对象:
Statement stmt = conn.createStatement();
4.执行命令
Resultset rs = stmt.excuteQuery(sql);
stmt.excuteUpdate(sql);
5、释放资源
closeRes();