EasyMall商品删除模块
可能出现的问题---【【更新丢失】】
解决方案
select * from table for update;#排它锁for update
乐观锁解决方案
乐观的认为,每次查询都不会造成更新的丢失,检测更新的丢失来进行相应的处理
1. 得到预料的值:select
2. select * from table and 检测的字段=预料的值;#乐观锁(判断理想中的条件是否成立)
3. 判断是否要回滚操作
EasyMall的解决方案
解决:查询该种类的剩余商品的时候添加悲观锁
public List findProdsByCategoryId(int category_id) {
List prod_list = new ArrayList();
try {
// 查询数据库,并把每一条记录包装成Prod对象存入prod_list列表中
conn = MySqlUtils.getConn();
stat = conn
.prepareStatement("select * from prod inner join prod_category where prod.prodCategory_id=prod_category.id and prod_category.id=? for update");//悲观锁解决方案(for update)
stat.setInt(1, category_id);
rs = stat.executeQuery();
while (rs.next()) {
Prod prod = new Prod();
prod.setId(rs.getInt(1));
prod.setName(rs.getString(2));
prod.setPnum(rs.getInt(4));
prod.setDescription(rs.getString(7));
prod.setImgurl(rs.getString(5));
prod.setPrice(rs.getDouble(3));
prod.setProdCategory_id(rs.getInt(6));
prod.setProdCategory(new ProdCategory(rs.getString(8), rs
.getString(9)));
prod_list.add(prod);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
return prod_list;
}
代码
页面
web
ManageProdDelServlet
package com.easymall.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.easymall.factory.BasicFactory;
import com.easymall.service.ProdService;
@SuppressWarnings("serial")
public class ManageProdDelServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取参数--商品的id
int id = Integer.parseInt(request.getParameter("id"));
// 通过id 删除对应的商品
ProdService service = BasicFactory.getFactory().getObj(
ProdService.class);
service.delProd(id);
// 返回商品列表界面
response.getWriter().write("删除成功!即将返回。。。");
response.setHeader("refresh", "2;url=ManagerProdListServlet");
}
}
service
ProdService
package com.easymall.service;
import java.util.List;
import com.easymall.domain.Prod;
public interface ProdService {
/**
* 添加一个产品
*
* @param prod
*/
public void addProd(Prod prod);
/**
* 查询所有的商品
*
* @return 查询所有的商品
*/
public List findProdList();
/**
* 通过id更新商品的pnum
*
* @param id
* @param pnum
*/
public void upDatePunm(int id, int pnum);
/**
* 通过id删除相应的产品
* @param id
*/
public void delProd(int id);
}
ProdServiceImpl
package com.easymall.service;
import java.util.List;
import com.easymall.dao.ProdDao;
import com.easymall.domain.Prod;
import com.easymall.domain.ProdCategory;
import com.easymall.factory.BasicFactory;
import com.easymall.utils.TransactionManager;
public class ProdServiceImpl implements ProdService {
private ProdDao prodDao = BasicFactory.getFactory().getObj(ProdDao.class);
public void addProd(Prod prod) {
try {
// 开启事务
TransactionManager.StartTransaction();
String category_id = "-666";
// 检查商品种类是否存在
ProdCategory category = prodDao.findProdCategoryByCategoryName(prod
.getProdCategory().getName());
if (category == null) {
// 商品种类不存在--则先添加商品种类,然后添加商品
category = prodDao
.addCategory(prod.getProdCategory().getName());// 返回值的作用是为了后期容易得到商品种类的ID值
}
// 获取商品种类的ID
category_id = category.getId();
// 商品种类存在,添加商品
prodDao.addProd(prod, category_id);
// 提交事务
TransactionManager.CommitTransaction();
// 关闭连接
TransactionManager.realse();
} catch (Exception e) {
e.printStackTrace();
// 事务回滚
TransactionManager.RollbackTransaction();
System.out.println("back");
throw new RuntimeException(e);
}
}
public List findProdList() {
return prodDao.findProdList();
}
public void upDatePunm(int id, int pnum) {
prodDao.upDatePnum(id, pnum);
}
public void delProd(int id) {
try {
TransactionManager.StartTransaction();// 开启事务
// 根据商品信息id查找对应的产品信息
Prod prod = prodDao.findProdById(id);
// 获取种类
int category_id = prod.getProdCategory_id();
// 根据种类获取该种类的剩余产品
List list_prod = prodDao.findProdsByCategoryId(category_id);
if (list_prod.size() > 1) {
// 如果大于1则只删除当前商品即可
prodDao.delProdById(id);
} else if (list_prod.size() == 1) {
// 如果为1的话,则将该商品和该种类都删除(级联删除)
prodDao.delProdById(id);
prodDao.delCategoryByCategoryId(category_id);
}
TransactionManager.CommitTransaction();// 提交事务
} catch (Exception e) {
e.printStackTrace();
TransactionManager.RollbackTransaction();// 回滚事务
throw new RuntimeException(e);
} finally {
// 释放资源
TransactionManager.realse();
}
}
}
dao
ProdDao
package com.easymall.dao;
import java.util.List;
import com.easymall.domain.Prod;
import com.easymall.domain.ProdCategory;
public interface ProdDao {
/**
* 通过商品种类名称查询数据库是否有此种类
*
* @param string
* @return 找到了? 商品种类的对象:null;
*/
ProdCategory findProdCategoryByCategoryName(String string);
/**
* 添加一个商品种类
*
* @param category
* @return 添加成功对应的商品种类
*/
ProdCategory addCategory(String category_name);
/**
* 添加商品
*
* @param prod
* 商品
* @param category_id
* 商品种类的ID
* @return void
*/
void addProd(Prod prod, String category_id);
/**
* 查询所有商品
*
* @return 商品列表
*/
List findProdList();
/**
* 通过id更新产品的pnum数据
*
* @param id
* @param pnum
*/
void upDatePnum(int id, int pnum);
/**
* 通过产品id查找对应的商品
*
* @param id
* @return 商品信息
*/
Prod findProdById(int id);
/**
* 通过中了的id查找对应的所有商品
*
* @param category_id
* @return 该种类对应的所有商品 ---list
*/
List findProdsByCategoryId(int category_id);
/**
* 通过商品的id删除商品
*
* @param id
*/
void delProdById(int id);
/**
* 通过商品种类的id删除改种类
*
* @param category_id
*/
void delCategoryByCategoryId(int category_id);
}
ProdDaoImpl
package com.easymall.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import com.easymall.domain.Prod;
import com.easymall.domain.ProdCategory;
import com.easymall.utils.MySqlUtils;
import com.easymall.utils.TransactionManager;
public class ProdDaoImpl implements ProdDao {
Connection conn = null;
PreparedStatement stat = null;
ResultSet rs = null;
public ProdCategory findProdCategoryByCategoryName(String name) {
try {
ProdCategory pc = null;
conn = TransactionManager.getConn();
stat = conn
.prepareStatement("select * from prod_category where name=?");
stat.setString(1, name);
rs = stat.executeQuery();
while (rs.next()) {// 一个对象这里才对----------嘻嘻
pc = new ProdCategory();
pc.setId(rs.getString("id"));
pc.setName(rs.getString("name"));
}
return pc;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
public ProdCategory addCategory(String category_name) {
try {
conn = TransactionManager.getConn();
conn.setAutoCommit(false);// 设置不自动提交
stat = conn
.prepareStatement("insert into prod_category(name) values(?)");
stat.setString(1, category_name);
stat.executeUpdate();
// 通过得到刚存入的数据得到相应的id来返回ProdCategory对象
ProdCategory pc = null;
stat = conn
.prepareStatement("select * from prod_category where name=? ");
stat.setString(1, category_name);
rs = stat.executeQuery();
while (rs.next()) {
pc = new ProdCategory();
pc.setId(rs.getString("id"));
pc.setName(rs.getString("name"));
}
return pc;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
public void addProd(Prod prod, String category_id) {
try {
conn = TransactionManager.getConn();
stat = conn
.prepareStatement("insert into prod(name,price,pnum,img_url,description,prodCategory_id) values(?,?,?,?,?,?)");
stat.setString(1, prod.getName());
stat.setDouble(2, prod.getPrice());
stat.setInt(3, prod.getPnum());
stat.setString(4, prod.getImgurl());
stat.setString(5, prod.getDescription());
stat.setInt(6, Integer.parseInt(category_id));
stat.executeUpdate();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
public List findProdList() {
List prod_list = new ArrayList();
try {
// 查询数据库,并把每一条记录包装成Prod对象存入prod_list列表中
conn = MySqlUtils.getConn();
stat = conn
.prepareStatement("select * from prod inner join prod_category where prod.prodCategory_id=prod_category.id");
rs = stat.executeQuery();
while (rs.next()) {
Prod prod = new Prod();
prod.setId(rs.getInt(1));
prod.setName(rs.getString(2));
prod.setPnum(rs.getInt(4));
prod.setDescription(rs.getString(7));
prod.setImgurl(rs.getString(5));
prod.setPrice(rs.getDouble(3));
prod.setProdCategory_id(rs.getInt(6));
prod.setProdCategory(new ProdCategory(rs.getString(8), rs
.getString(9)));
prod_list.add(prod);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
MySqlUtils.close(conn, stat, rs);
}
return prod_list;
}
public void upDatePnum(int id, int pnum) {
try {
// 通过id更新产品的pnum
conn = MySqlUtils.getConn();
stat = conn.prepareStatement("update prod set pnum=? where id=? ");
stat.setInt(1, pnum);
stat.setInt(2, id);
stat.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Prod findProdById(int id) {
try {
Prod prod = null;
conn = TransactionManager.getConn();
stat = conn
.prepareStatement("select * from prod inner join prod_category where prod.prodCategory_id=prod_category.id and prod.id=?");
stat.setInt(1, id);
rs = stat.executeQuery();
while (rs.next()) {
prod = new Prod();
prod.setId(rs.getInt(1));
prod.setName(rs.getString(2));
prod.setPnum(rs.getInt(4));
prod.setDescription(rs.getString(7));
prod.setImgurl(rs.getString(5));
prod.setPrice(rs.getDouble(3));
prod.setProdCategory_id(rs.getInt(6));
prod.setProdCategory(new ProdCategory(rs.getString(8), rs
.getString(9)));
}
return prod;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
public List findProdsByCategoryId(int category_id) {
List prod_list = new ArrayList();
try {
// 查询数据库,并把每一条记录包装成Prod对象存入prod_list列表中
conn = MySqlUtils.getConn();
stat = conn
.prepareStatement("select * from prod inner join prod_category where prod.prodCategory_id=prod_category.id and prod_category.id=? for update");// 悲观锁解决更新丢失
stat.setInt(1, category_id);
rs = stat.executeQuery();
while (rs.next()) {
Prod prod = new Prod();
prod.setId(rs.getInt(1));
prod.setName(rs.getString(2));
prod.setPnum(rs.getInt(4));
prod.setDescription(rs.getString(7));
prod.setImgurl(rs.getString(5));
prod.setPrice(rs.getDouble(3));
prod.setProdCategory_id(rs.getInt(6));
prod.setProdCategory(new ProdCategory(rs.getString(8), rs
.getString(9)));
prod_list.add(prod);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
return prod_list;
}
public void delProdById(int id) {
try {
conn = TransactionManager.getConn();
stat = conn.prepareStatement("delete from prod where id=?");
stat.setInt(1, id);
stat.executeUpdate();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
public void delCategoryByCategoryId(int category_id) {
try {
conn = TransactionManager.getConn();
stat = conn
.prepareStatement("delete from prod_category where id=?");
stat.setInt(1, category_id);
stat.executeUpdate();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
MySqlUtils.close(null, stat, rs);
}
}
}