[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 ...
随机推荐
- sql 创建新表时的完成格式
1 create table [dbo].[Customer] ( CustomerID int identity(1,1) not null, [Name] [nvarchar](50) null, ...
- LEANGOO卡片
转自:https://www.leangoo.com/leangoo_guide/leangoo_cards.html#toggle-id-10 Leangoo的卡片可以是需求.目标.任务.问题.缺陷 ...
- Java,JavaScript和ABAP通过代码取得当前代码的调用栈Callstack
Java StackTraceElement stack[] = Thread.currentThread().getStackTrace(); System.out.println("Ca ...
- vue项目,子页面刷新404问题
翻车事故分析: 因需对项目整体优化,调整过程,采用了路由的history模式,本地项目运行,刷新子页面都是OK的. 部署到测试服务器,正常跳转都ok,但刷新子页面就会出现404,请求变成了get,没有 ...
- JPA自带findOne方法报错原因
是由于jdk8的原因,有可能和spring boot的版本也关系, 两种方式可选 注册,返回类是Optional<Girl>, Optional是jdk8自带的 @GetMapping(v ...
- PHP中pdo的使用
<?php /** *下面代码中information为表名 * */ //1.先要连数据库 $pdo=new PDO('mysql:host=localhost;dbname=数据库名','用 ...
- JS和jQuery用法区别
目录 JS和jQuery用法区别 外观区别 查找元素 操作标签 操作内容 操作属性 操作位置 操作样式 事件 JS和jQuery用法区别 外观区别 jQuery与JS最直观的区别就是外观上jQuery ...
- 【Day3】项目实战。百度针对Xpath的反爬策略和解决方式
import lxml.etree as le with open('edu.html','r',encoding='utf-8') as f: html = f.read() html_x = le ...
- [shell] shell echo打印换行的方法
echo要支持同C语言一样的\转义功能,只需要加上参数-e,如下所示: echo -e hello \n echo \n
- 图像处理---《Mat对象 与 IplImage对象》
图像处理---<认识 Mat对象> Mat对象 与 IplImage对象 (1)Mat对象:OpenCV2.0之后引进的图像数据结构.自动分配内存.不存在内存泄漏的问题,是面向对象的数据结 ...