【springmvc+mybatis项目实战】杰信商贸-19.级联删除

我们从写项目开始到现在,一共完成了生产厂家、购销合同、货物(购销合同下的)、附件(货物下的)这四大块的大部分业务。

我们的生产厂家、购销合同、货物(购销合同下的)、附件(货物下的)这四大块的关系我们来回顾一下:



我们先不管生产厂家(因为它可以和后三个关联关系最弱)。
购销合同与货物是一对多的关系,而货物与附件又是一对多的关系。那么购销合同与附件是两层一对多的关系。这里我们要注意,在两层一对多结构中,子表数据不设置外键关联时,就称为僵尸数据。

因为我们的购销合同、货物、附件表虽然都存储有关联关系的表的主键的字段,但是并没有设置外键,加入当我们删除购销合同时,我们之前写的删除方法就已经不行了,删除了购销合同后,并没有将购销合同下的所有货物,以及货物的所有附件删除。

所以接下来我们要利用“级联删除”,来解决我们为了图省事而没有设外键引发的问题。
我们来看一下“级联删除”:

Hibernate 多层关联最简单;配置关联关系时,只关系上下级对象。(hibernate的强项)
Mybatis 多层关联关系时,级联删除必须一级一级的删除。多级时要专门写mapper方法。(这就是MyBatis的弱项,官方没有办法解决= =,只能通过你自己的办法解决)

有两种级联映射的方法:

1)在mybatis在service,删除货物时,先调用附件的service删除方法
2)通过sql,高速删除(批量删除)每层都要实现一个删除

我们使用第二种方法解决刚刚我们所说的问题,就要分别在货物和购销合同的Mapper下增加级联删除的SQL配置

首先我们在附件的ContractProductMapper.xml中添加级联删除的代码:
[html]  view plain copy
  1. <!-- 级联删除 -->  
  2. <delete id="deleteByContractProductById" parameterType="string">  
  3.     delete from ext_cproduct_c  
  4.     where contract_product_id in  
  5.     <foreach collection="array" item="id" open="(" close=")" separator=",">  
  6.         #{id}  
  7.     </foreach>  
  8. </delete>  

然后在货物的ContractMapper.xml中添加级联删除的代码:
[html]  view plain copy
  1. <pre name="code" class="html"><!-- 级联删除 删除合同时同时删除合同下的货物-->  
  2. <delete id="deleteByContractById" parameterType="string">  
  3.     delete from contract_product_c  
  4.     where contract_id in  
  5.     <foreach collection="array" item="id" open="(" close=")" separator=",">  
  6.         #{id}  
  7.     </foreach>  
  8. </delete>  
  9.   
  10. <!-- 级联删除 删除合同时删除合同货物下的所有附件-->  
  11. <delete id="deleteExtByContractById" parameterType="string">  
  12.     delete from ext_cproduct_c  
  13.     where contract_product_id in(  
  14.         select contract_product_id from contract_product_c  
  15.         where contract_id in  
  16.         <foreach collection="array" item="id" open="(" close=")" separator=",">  
  17.             #{id}  
  18.         </foreach>  
  19.     )  
  20. </delete>  
 
先来给ContractProduct来加新的级联删除的逻辑:首先是Dao层ContractProductDao.java: 
[java]  view plain copy
  1. package cn.hpu.jk.dao;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import cn.hpu.jk.domain.ContractProduct;  
  6.   
  7. public interface ContractProductDao extends BaseDao<ContractProduct>{  
  8.     //我们这里可以直接使用继承的BaseDao的增删改查方法  
  9.     //创建一系列其它Dao的原因是因为其它Dao有可能需要拓展  
  10.       
  11.     //拓展的级联删除方法  
  12.     public void deleteByContractProductById(Serializable[] ids) throws Exception;  
  13. }  

ContractProductDaoImpl.java:
[java]  view plain copy
  1. package cn.hpu.jk.dao.impl;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import org.springframework.stereotype.Repository;  
  6.   
  7. import cn.hpu.jk.dao.ContractProductDao;  
  8. import cn.hpu.jk.domain.ContractProduct;  
  9.   
  10.   
  11. @Repository //为了包扫描的时候这个Dao被扫描到  
  12. public class ContractProductDaoImpl extends BaseDaoImpl<ContractProduct> implements ContractProductDao{  
  13.       
  14.     public ContractProductDaoImpl(){  
  15.         //设置命名空间  
  16.         super.setNs("cn.hpu.jk.mapper.ContractProductMapper");  
  17.     }  
  18.   
  19.   
  20.     @Override  
  21.     public void deleteByContractProductById(Serializable[] ids) throws Exception {  
  22.         super.getSqlSession().delete(super.getNs()+".deleteByContractProductById", ids);  
  23.           
  24.     }  
  25.   
  26.   
  27. }  

接下来是Service层,我们这里不用添加新的方法,只需要修改原来的删除方法即可。
在ContractProductServiceImpl中修改下面方法
[java]  view plain copy
  1. //删除多个  
  2. @Override  
  3. public void delete(Serializable[] ids) {  
  4.     try {  
  5.         //先删除所有货物下的附件  
  6.         contractProductDao.deleteByContractProductById(ids);  
  7.     } catch (Exception e) {  
  8.         // TODO Auto-generated catch block  
  9.         e.printStackTrace();  
  10.     }  
  11.     contractProductDao.delete(ids);  
  12. }  
  13.   
  14.   
  15. //删除一个  
  16. @Override  
  17. public void deleteById(Serializable id) {  
  18.     Serializable[] ids={id};  
  19.     try {  
  20.         //先删除所有货物下的附件  
  21.         contractProductDao.deleteByContractProductById(ids);  
  22.     } catch (Exception e) {  
  23.         // TODO Auto-generated catch block  
  24.         e.printStackTrace();  
  25.     }  
  26.     contractProductDao.deleteById(id);  
  27. }  

下面重启服务器进行测试:
我们进入购销合同列表,我们测试第一条购销合同的数据,点击它的“货物”



我们可以看到此购销合同下有两条记录,我们点击第一条(厂家为“喜福来”)数据的“附件”



发现第一条货物下有2个附件,分别来自“瑞成电镀厂”和“综艺花纸”。

观察一下数据库,这两条数据也是存在的。


我们在货物那一层进行删除,我们删除第一条(厂家为“喜福来”)数据。



然后我们回到数据库中,发现来自“瑞成电镀厂”和“综艺花纸”的附件已经被删除了:

所以我们货物和附件的级联删除完成。


同理我们在购销合同下也是这么做
首先是Dao层
ContractDao.java:
[java]  view plain copy
  1. package cn.hpu.jk.dao;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Map;  
  5.   
  6. import cn.hpu.jk.domain.Contract;  
  7.   
  8. public interface ContractDao extends BaseDao<Contract>{  
  9.     //我们这里可以直接使用继承的BaseDao的增删改查方法  
  10.     //创建一系列其它Dao的原因是因为其它Dao有可能需要拓展  
  11.       
  12.     public void updateState(Map map);//修改状态  
  13.       
  14.     //拓展的级联删除方法  
  15.     public void deleteByContractById(Serializable[] ids) throws Exception;  
  16.     public void deleteExtByContractById(Serializable[] ids) throws Exception;  
  17. }  

ContractDaoImpl.java:
[java]  view plain copy
  1. package cn.hpu.jk.dao.impl;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Map;  
  5.   
  6. import org.springframework.stereotype.Repository;  
  7.   
  8.   
  9. import cn.hpu.jk.dao.ContractDao;  
  10. import cn.hpu.jk.domain.Contract;  
  11.   
  12.   
  13. @Repository //为了包扫描的时候这个Dao被扫描到  
  14. public class ContractDaoImpl extends BaseDaoImpl<Contract> implements ContractDao{  
  15.       
  16.     public ContractDaoImpl(){  
  17.         //设置命名空间  
  18.         super.setNs("cn.hpu.jk.mapper.ContractMapper");  
  19.     }  
  20.   
  21.   
  22.     @Override  
  23.     public void updateState(Map map) {  
  24.         super.getSqlSession().update(super.getNs()+".updateState", map);  
  25.     }  
  26.   
  27.   
  28.     @Override  
  29.     public void deleteByContractById(Serializable[] ids) throws Exception {  
  30.         super.getSqlSession().update(super.getNs()+".deleteByContractById", ids);  
  31.     }  
  32.   
  33.   
  34.     @Override  
  35.     public void deleteExtByContractById(Serializable[] ids) throws Exception {  
  36.         super.getSqlSession().update(super.getNs()+".deleteExtByContractById", ids);  
  37.           
  38.     }  
  39. }  

然后是Service层,在ContractServiceImpl中修改下面方法
[java]  view plain copy
  1. @Override  
  2. public void delete(Serializable[] ids) {  
  3.       
  4.     try {  
  5.         //删除合同时删除合同货物下的所有附件  
  6.         contractDao.deleteExtByContractById(ids);  
  7.     } catch (Exception e1) {  
  8.         // TODO Auto-generated catch block  
  9.         e1.printStackTrace();  
  10.     }  
  11.       
  12.     try {  
  13.         //删除合同时同时删除合同下的货物  
  14.         contractDao.deleteByContractById(ids);  
  15.     } catch (Exception e) {  
  16.         // TODO Auto-generated catch block  
  17.         e.printStackTrace();  
  18.     }  
  19.     contractDao.delete(ids);  
  20. }  
  21.   
  22.   
  23. @Override  
  24. public void deleteById(Serializable id) {  
  25.     Serializable[] ids={id};  
  26.       
  27.     try {  
  28.         //删除合同时删除合同货物下的所有附件  
  29.         contractDao.deleteExtByContractById(ids);  
  30.     } catch (Exception e1) {  
  31.         // TODO Auto-generated catch block  
  32.         e1.printStackTrace();  
  33.     }  
  34.       
  35.     try {  
  36.         //删除合同时同时删除合同下的货物  
  37.         contractDao.deleteByContractById(ids);  
  38.     } catch (Exception e) {  
  39.         // TODO Auto-generated catch block  
  40.         e.printStackTrace();  
  41.     }  
  42.     contractDao.deleteById(id);  
  43. }  

我们进行测试,现在我又添加了一些测试数据,首先我们点击第三条购销合同数据

发现其下有2条货物数据



点击“康达”的货物信息(我只在康达下增加了附件,“平遥远江”下没有附件),下面又有两条附件数据



并且我们的货物以及附件数据在数据库中都存在


接下来,我们删除第三条购销合同数据


然后去数据库中查看,发现合同下的货物,合同下货物的附件信息已经全部删除完毕


至此,我们的级联删除功能完成!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值