[MySql]MySql中外键设置 以及Java/MyBatis程序对存在外键关联无法删除的规避
在MySql设定两张表,其中product表的主键设定成orderTb表的外键,具体如下:
产品表:
create table product(id INT(11) PRIMARY KEY,name VARCHAR(32) );
订单表:
create table orderTb(id INT(11) PRIMARY KEY,productid INT(11), FOREIGN KEY(productid) REFERENCES product(id) );
给产品表插入数据如下:

给订单表插入数据如下:

在MySql-Front工具中写SQL文“DELETE from product where id=1”,由于主外键关联,工具会如下报错:

如果用java程序去删(工程下载:https://files.cnblogs.com/files/xiandedanteng/product191006_2.rar )
删除代码:
package com.hy;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
public class DeleteProductTest {
private static Logger logger = Logger.getLogger(DeleteProductTest.class);
public static void main(String[] args) throws Exception{
long startTime = System.currentTimeMillis();
Reader reader=Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(reader);
reader.close();
SqlSession session=ssf.openSession();
logger.info("Commit Status="+session.getConnection().getAutoCommit());
try {
ProductMapper pm=session.getMapper(ProductMapper.class);
int changed=pm.deleteById(1);
session.commit();
logger.info("Committed! Chenged Record Num="+changed);
long endTime = System.currentTimeMillis();
logger.info("Time elapsed:" + toDhmsStyle((endTime - startTime)/1000) + ".");
}catch(Exception ex) {
logger.error("Error/Exception happened when executing the meothod'ProductMapper.deleteById(1)' because '"+ex.getMessage()+"'.");
session.rollback();
logger.info("Rollbacked.");
}
finally {
session.close();
}
}
// format seconds to day hour minute seconds style
// Example 5000s will be formatted to 1h23m20s
public static String toDhmsStyle(long allSeconds) {
String DateTimes = null;
long days = allSeconds / (60 * 60 * 24);
long hours = (allSeconds % (60 * 60 * 24)) / (60 * 60);
long minutes = (allSeconds % (60 * 60)) / 60;
long seconds = allSeconds % 60;
if (days > 0) {
DateTimes = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
} else if (hours > 0) {
DateTimes = hours + "h" + minutes + "m" + seconds + "s";
} else if (minutes > 0) {
DateTimes = minutes + "m" + seconds + "s";
} else {
DateTimes = seconds + "s";
}
return DateTimes;
}
}
Mapper接口类
package com.hy;
public interface ProductMapper {
int deleteById(long id);
}
Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.hy.ProductMapper">
<delete id="deleteById">
delete from product where id=#{id}
</delete>
</mapper>
用程序强行去删,会出现异常:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
执行下来,控制台输出会是:
INFO [main] - Commit Status=false ERROR [main] - Error/Exception happened when executing the meothod'ProductMapper.deleteById(1)' because ' ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`orderTb`, CONSTRAINT `orderTb_ibfk_1` FOREIGN KEY (`productid`) REFERENCES `product` (`id`)) ### The error may involve defaultParameterMap ### The error occurred while setting parameters ### SQL: delete from product where id=? ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`orderTb`, CONSTRAINT `orderTb_ibfk_1` FOREIGN KEY (`productid`) REFERENCES `product` (`id`))'. INFO [main] - Rollbacked.
因此,在删除时,应该有选择地辨认并跳过这种异常才行。具体程序如下:
package com.hy;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;
public class DeleteProductTest2 {
private static Logger logger = Logger.getLogger(DeleteProductTest2.class);
public static void main(String[] args) throws Exception{
long startTime = System.currentTimeMillis();
Reader reader=Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(reader);
reader.close();
SqlSession session=ssf.openSession();
logger.info("Commit Status="+session.getConnection().getAutoCommit());
int totalChanged=0;
try {
ProductMapper pm=session.getMapper(ProductMapper.class);
long[] arr= {1,2,3,4,5};
for(long id:arr) {
logger.info("deleteById id="+id+" started!");
try {
int changed=pm.deleteById(id);
session.commit();
totalChanged+=changed;
logger.info("Committed! Chenged Record Num="+changed);
}catch(Exception ex) {
if(ex.getMessage().contains("foreign key constraint fails")){ // 用 ex instanceof 识别不出来,故而用这种方式
logger.error("ForeignKey collide Conflict happened when executing the meothod'ProductMapper.deleteById("+id+")'.");
continue;
}else {
logger.error("Other Error/Exception happened when executing the meothod'ProductMapper.deleteById("+id+")' because '"+ex.getMessage()+"'.");
session.rollback();
logger.info("Rollbacked.");
}
}
logger.info("deleteById id="+id+" finished!");
}
}catch(Exception ex) {
logger.error("Error/Exception happened when executing the meothod'ProductMapper.deleteById(1)' because '"+ex.getMessage()+"'.");
session.rollback();
logger.info("Rollbacked.");
}
finally {
session.close();
}
logger.info("Changed recoed count="+totalChanged);
long endTime = System.currentTimeMillis();
logger.info("Time elapsed:" + toDhmsStyle((endTime - startTime)/1000) + ".");
}
// format seconds to day hour minute seconds style
// Example 5000s will be formatted to 1h23m20s
public static String toDhmsStyle(long allSeconds) {
String DateTimes = null;
long days = allSeconds / (60 * 60 * 24);
long hours = (allSeconds % (60 * 60 * 24)) / (60 * 60);
long minutes = (allSeconds % (60 * 60)) / 60;
long seconds = allSeconds % 60;
if (days > 0) {
DateTimes = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
} else if (hours > 0) {
DateTimes = hours + "h" + minutes + "m" + seconds + "s";
} else if (minutes > 0) {
DateTimes = minutes + "m" + seconds + "s";
} else {
DateTimes = seconds + "s";
}
return DateTimes;
}
}
执行后输出如下:
INFO [main] - Commit Status=false INFO [main] - deleteById id=1 started! ERROR [main] - ForeignKey collide Conflict happened when executing the meothod'ProductMapper.deleteById(1)'. INFO [main] - deleteById id=2 started! ERROR [main] - ForeignKey collide Conflict happened when executing the meothod'ProductMapper.deleteById(2)'. INFO [main] - deleteById id=3 started! ERROR [main] - ForeignKey collide Conflict happened when executing the meothod'ProductMapper.deleteById(3)'. INFO [main] - deleteById id=4 started! INFO [main] - Committed! Chenged Record Num=1 INFO [main] - deleteById id=4 finished! INFO [main] - deleteById id=5 started! INFO [main] - Committed! Chenged Record Num=1 INFO [main] - deleteById id=5 finished! INFO [main] - Changed recoed count=2 INFO [main] - Time elapsed:10s.
--END-- 2019年10月6日14:52:46
[MySql]MySql中外键设置 以及Java/MyBatis程序对存在外键关联无法删除的规避的更多相关文章
- Java MyBatis 插入数据库返回主键
最近在搞一个电商系统中由于业务需求,需要在插入一条产品信息后返回产品Id,刚开始遇到一些坑,这里做下笔记,以防今后忘记. 类似下面这段代码一样获取插入后的主键 User user = new User ...
- mysql级联更新的两种方式:触发器更新和外键
1.mysql级联更新有两种方式:触发器更新和外键更新. 2.触发器更新和外键更新的目的都是为了保证数据完整性. 我们通常有这样的需求:删除表Table 1中记录,需要同时删除其它表中与Table 1 ...
- mysql概要(十四)(二)索引(补充:外键级联操作)
[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ] [ ON UPDATE { NO ACTION | CASCADE | S ...
- Java MyBatis 插入数据库返回主键--insertSelective这样就不用每次到数据库里面查询了
insertSelective---Java MyBatis 插入数据库返回主键--insertSelective这样就不用每次到数据库里面查询了 https://www.cnblogs.com/xi ...
- powerdesigner设置主键为自增字段,设置非主键为唯一键并作为表的外键
转自:https://www.cnblogs.com/CoffeeHome/archive/2014/06/04/3767501.html 这里powerdesigner连接的数据库是以mysql为例 ...
- MySQL:如何导入导出数据表和如何清空有外建关联的数据表
1.导入导出 导入数据库:前提:数据库和数据表要存在(已经被创建) (1)将数据表 test_user.sql 导入到test 数据库的test_user 表中 [root@test ~]# mysq ...
- java之hibernate之基于外键的双向一对一关联映射
这篇讲解 基于外键的双向一对一关联映射 1.考察如下信息,人和身份证之间是一个一对一的关系.表的设计 2.类结构 Person.java public class Person implements ...
- java之hibernate之基于外键的一对一单向关联映射
这篇讲解基于外键的一对一单向关联映射 1.考察如下信息,人和身份证之间是一个一对一的关系.表的设计 注意:基于外键的一对一关联的表结构和多对一的表结构是一致的,但是,外键是唯一的. 2.类的结构 Pe ...
- 一个7重嵌套表EF添加语句,注意子表赋值过程中只需写子表主键赋值,不需要写子表外键=父表主键。EF创建时会自动将子表外键设为与父表主键相等
AIRPORT_HELIPORT tt = new AIRPORT_HELIPORT() { AIRPORT_HELIPORT_UUID = Gui ...
随机推荐
- echarts —— 重叠图
平时做堆叠图比较多,但是今天遇到一个要做重叠图的需求,记录一下~ 1.堆叠图,对应的 series: [] ,需要设置一个stack: "1",其中每个堆叠图的stack属性值都要 ...
- 16.SpringMVC核心技术-文件上传
上传单个文件 1.定义具有文件上传功能的页面 index.jsp,其表单的设置需要注意,method 属性为 POST, enctype 属性为 multipart/form-data.另外,需要注意 ...
- 【Day3】1.正则表达式
1.正则表达式 2.案例 关闭贪婪模式
- linux基础5-vi文本处理器
三种模式下各自可以完成的操作: 一般模式:可以完成光标移动.删除单个和整行字.复制和黏贴,通过i.o.a.r这几个命令进入编辑模式 编辑模式:可以输入字符,通过esc返回一般模式 指令模式:读取文件, ...
- linux 设备驱动与应用程序异步通知
一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...
- String 属于基础的数据类型吗?(未完成)
String 属于基础的数据类型吗?(未完成)
- exec sp_executesql 比直接执行SQL慢,而且消耗大量资源问题
今天SqlServer数据库出现了访问不通的情况,抓紧重启了下服务,让大家先恢复使用,然后我开了 SQL Server Profiler 看看是不是存在性能问题SQL,然后就发现一批这样的SQL,看r ...
- Java基础知识学习01
0 项目,包,文件,类 Mytest是自己建的java工程,包含src和JRE System Libery.其中src是存放自己的代码的地方,JRE包含程序运行时所需要的各种文件:在src下包含Tes ...
- 015_linuxC++之_覆写
34.类成员函数的重载.覆盖和隐藏区别?答案:a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函 ...
- virtualBox中有线和无线两种情况下centos虚拟机和本地机互ping的方案
之前写微信点餐系统的时候,刚开始是无线连接,然后每次进去虚拟机ip和本地ip都会改变,所以每次都需要配置一下nginx,还有本地的路径.之后换有线连接,就研究了一下桥接模式有线情况下虚拟机静态ip设置 ...