[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 ...
随机推荐
- Outline 科学的上网
outline 官网:https://getoutline.org/zh-CN/home 下载 Outline 管理器 下载 Outline 客户端 配置浏览器代理
- 【atcoder】GP 2 [agc036C]
题目传送门:https://atcoder.jp/contests/agc036/tasks/agc036_c 题目大意:给你一个长度为$N$初始全0的序列,每次操作你可以找两个不同的元素,一个自增1 ...
- 【JAVA各版本特性】JAVA 1.0 - JAVA 12
make JDK Version 1.01996-01-23 Oak(橡树) 初代版本,伟大的一个里程碑,但是是纯解释运行,使用外挂JIT,性能比较差,运行速度慢. JDK Version 1.119 ...
- Linux内核的目录结构
- RabbitMQ 功能
学习完了rabbitmq总一下 RabbitMQ依赖的语言 erlang 第一它可以实现不同程序之间的程序信息储存交互,在易用性.扩展性.高可用性的方面不俗. rabbitmq相当于一个中间人,我们同 ...
- 微信小程序开发(八)获取手机ip地址
// succ.wxml <view>手机IP:{{motto.query}}</view> // succ.js var app = getApp() Page({ data ...
- Js操作DOM元素及获取浏览器高宽
在JavaScript中,经常会来获取Document文档元素,是 HTML 文档对象模型的英文缩写,Document Object Model for HTML,是基于浏览器编程,HTML DOM ...
- 5.caffe:train.sh 和 test.sh (训练与测试 )
一,train.sh #!/usr/bin/env sh ./build/tools/caffe train --solver=myself/00b/solver.prototxt # cd CAFF ...
- java线程基础巩固---如何实现一个自己的显式锁Lock
拋出synchronized问题: 对于一个方法上了同锁如果被一个线程占有了,而假如该线程长时间工作,那其它线程不就只能傻傻的等着,而且是无限的等这线程工作完成了才能执行自己的任务,这里来演示一下这种 ...
- UTC和GMT时间
来源:https://www.cnblogs.com/qiuyi21/archive/2008/03/04/1089456.html UTC和GMT时间 每个地区都有自己的本地时间,在网上以及无线电通 ...