您的位置:首页 > 编程语言 > Java开发

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

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

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



我们先不管生产厂家(因为它可以和后三个关联关系最弱)。

购销合同与货物是一对多的关系,而货物与附件又是一对多的关系。那么购销合同与附件是两层一对多的关系。这里我们要注意,在两层一对多结构中,子表数据不设置外键关联时,就称为僵尸数据。

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

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

我们来看一下“级联删除”:

Hibernate 多层关联最简单;配置关联关系时,只关系上下级对象。(hibernate的强项)

Mybatis 多层关联关系时,级联删除必须一级一级的删除。多级时要专门写mapper方法。(这就是MyBatis的弱项,官方没有办法解决= =,只能通过你自己的办法解决)

有两种级联映射的方法:

1)在mybatis在service,删除货物时,先调用附件的service删除方法

2)通过sql,高速删除(批量删除)每层都要实现一个删除

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

首先我们在附件的ContractProductMapper.xml中添加级联删除的代码:
<!-- 级联删除 -->
<delete id="deleteByContractProductById" parameterType="string">
delete from ext_cproduct_c
where contract_product_id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>


然后在货物的ContractMapper.xml中添加级联删除的代码:
<pre name="code" class="html"><!-- 级联删除 删除合同时同时删除合同下的货物-->
<delete id="deleteByContractById" parameterType="string">
delete from contract_product_c
where contract_id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>

<!-- 级联删除 删除合同时删除合同货物下的所有附件-->
<delete id="deleteExtByContractById" parameterType="string">
delete from ext_cproduct_c
where contract_product_id in(
select contract_product_id from contract_product_c
where contract_id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
)
</delete>


先来给ContractProduct来加新的级联删除的逻辑:首先是Dao层ContractProductDao.java:
package cn.hpu.jk.dao;

import java.io.Serializable;

import cn.hpu.jk.domain.ContractProduct;

public interface ContractProductDao extends BaseDao<ContractProduct>{
//我们这里可以直接使用继承的BaseDao的增删改查方法
//创建一系列其它Dao的原因是因为其它Dao有可能需要拓展

//拓展的级联删除方法
public void deleteByContractProductById(Serializable[] ids) throws Exception;
}


ContractProductDaoImpl.java:
package cn.hpu.jk.dao.impl;

import java.io.Serializable;

import org.springframework.stereotype.Repository;

import cn.hpu.jk.dao.ContractProductDao;
import cn.hpu.jk.domain.ContractProduct;

@Repository //为了包扫描的时候这个Dao被扫描到
public class ContractProductDaoImpl extends BaseDaoImpl<ContractProduct> implements ContractProductDao{

public ContractProductDaoImpl(){
//设置命名空间
super.setNs("cn.hpu.jk.mapper.ContractProductMapper");
}

@Override
public void deleteByContractProductById(Serializable[] ids) throws Exception {
super.getSqlSession().delete(super.getNs()+".deleteByContractProductById", ids);

}

}


接下来是Service层,我们这里不用添加新的方法,只需要修改原来的删除方法即可。

在ContractProductServiceImpl中修改下面方法
//删除多个
@Override
public void delete(Serializable[] ids) {
try {
//先删除所有货物下的附件
contractProductDao.deleteByContractProductById(ids);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
contractProductDao.delete(ids);
}

//删除一个
@Override
public void deleteById(Serializable id) {
Serializable[] ids={id};
try {
//先删除所有货物下的附件
contractProductDao.deleteByContractProductById(ids);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
contractProductDao.deleteById(id);
}


下面重启服务器进行测试:

我们进入购销合同列表,我们测试第一条购销合同的数据,点击它的“货物”



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



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



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



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



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



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

同理我们在购销合同下也是这么做

首先是Dao层

ContractDao.java:
package cn.hpu.jk.dao;

import java.io.Serializable;
import java.util.Map;

import cn.hpu.jk.domain.Contract;

public interface ContractDao extends BaseDao<Contract>{
//我们这里可以直接使用继承的BaseDao的增删改查方法
//创建一系列其它Dao的原因是因为其它Dao有可能需要拓展

public void updateState(Map map);//修改状态

//拓展的级联删除方法
public void deleteByContractById(Serializable[] ids) throws Exception;
public void deleteExtByContractById(Serializable[] ids) throws Exception;
}


ContractDaoImpl.java:
package cn.hpu.jk.dao.impl;

import java.io.Serializable;
import java.util.Map;

import org.springframework.stereotype.Repository;

import cn.hpu.jk.dao.ContractDao;
import cn.hpu.jk.domain.Contract;

@Repository //为了包扫描的时候这个Dao被扫描到
public class ContractDaoImpl extends BaseDaoImpl<Contract> implements ContractDao{

public ContractDaoImpl(){
//设置命名空间
super.setNs("cn.hpu.jk.mapper.ContractMapper");
}

@Override
public void updateState(Map map) {
super.getSqlSession().update(super.getNs()+".updateState", map);
}

@Override
public void deleteByContractById(Serializable[] ids) throws Exception {
super.getSqlSession().update(super.getNs()+".deleteByContractById", ids);
}

@Override
public void deleteExtByContractById(Serializable[] ids) throws Exception {
super.getSqlSession().update(super.getNs()+".deleteExtByContractById", ids);

}
}


然后是Service层,在ContractServiceImpl中修改下面方法
@Override
public void delete(Serializable[] ids) {

try {
//删除合同时删除合同货物下的所有附件
contractDao.deleteExtByContractById(ids);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

try {
//删除合同时同时删除合同下的货物
contractDao.deleteByContractById(ids);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
contractDao.delete(ids);
}

@Override
public void deleteById(Serializable id) {
Serializable[] ids={id};

try {
//删除合同时删除合同货物下的所有附件
contractDao.deleteExtByContractById(ids);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

try {
//删除合同时同时删除合同下的货物
contractDao.deleteByContractById(ids);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
contractDao.deleteById(id);
}


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



发现其下有2条货物数据



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



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



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



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



至此,我们的级联删除功能完成!

思考:我们每次删除完都要去下一级或者数据库看看我们删除了没有,可不可以直接在合同列表中显示每个合同下的货物有多少件?可不可以在货物列表下显示每个货物下有多少个附件?答案当然是可以,我们下一篇总结再详谈。

转载请注明出处:http://blog.csdn.net/acmman/article/details/48595867
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: