oracle触发器导致的hibernate违反完整性约束, (*) - 未找到父项关键字

本文介绍了在使用Oracle数据库和Hibernate时遇到的外键约束错误,原因是由于数据库触发器与Hibernate的主键生成策略冲突。通过删除触发器问题得到解决,同时提供了关于触发器和主键生成的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在做项目的时候,出现了hibernate违反完整性约束, (*) - 未找到父项关键字,这个错误其实不难理解。很多时候我们只有是什么原因导致的。但是,不知道具体原因和解决的方法。当然出现了这个问题的时候,改来改去好像没怎么可能呀!配置文件也没太大的问题,都是sequence.保存的时候也是新建了多的一方对象之后放入一个集合直接set到一的一方中。困扰很久之后,试想把触发器before insert给删除了。结果问题就解决了。

情景和原因分析可以参考以下网络资料:

解决的方法可以删除触发器,如果非要用的话,就得另想法子了!

问题:

自己做一个小实验,oracle数据库,使用hibernate作为中间件。在保存多对多关系时始终抛出一个外键约束的错误,大体内容如下:

(0 ms) [main] WARN : org.hibernate.util.JDBCExceptionReporter#logExceptions : SQL Error: 2291, SQLState: 23000

(10 ms) [main] ERROR: org.hibernate.util.JDBCExceptionReporter#logExceptions : ORA-02291: 违反完整约束条件 (STOCK.FK_INDUSTRY_R_STO_R_INDUSTRY) - 未找到父项关键字

 

(10 ms) [main] WARN : org.hibernate.util.JDBCExceptionReporter#logExceptions : SQL Error: 2291, SQLState: 23000

(10 ms) [main] ERROR: org.hibernate.util.JDBCExceptionReporter#logExceptions : ORA-02291: 违反完整约束条件 (STOCK.FK_INDUSTRY_R_STO_R_INDUSTRY) - 未找到父项关键字

数据库:

stock表和industry表是多对多的关系,中间表是industry_r_stock。使用powerdesigner设计的数据库。数据的脚本大致分为三部分:

1.       创建sequence

2.       创建数据库

3.       给库表添加before insert触发器

在代码中每个库表对应的文件,都配置了sequence的主键生成机制:

            <generator class="sequence" >

                     <param name="sequence">SEQUENCE_stock</param>

            </generator>

原因:

大体情况就是这样,现在说说产生问题的原因,经过反复检查,非常确定我的库表不存在外键约束定义上的问题,hibernate配置文件中的对应关系也没有问题,就是在保存stock时,无法保存中间表的数据,反复抛出上面的异常。

问题就出在使用powerdesigner设计pdm时,定义了主键的sequence,pd会创建before insert触发器:

CREATE TRIGGER TIB_BASIC_INFO BEFORE INSERT ON BASIC_INFO FOR EACH ROW

BEGIN

    SELECT SEQUENCE_stock.NEXTVAL INTO :NEW.ID FROM DUAL;

END;

每当有数据插入时,就会从序列中取出最新的值。但是,当我们使用hibernate作为中间件保存一个对象的时候,第一件事情就是查询库表主键的sequence(假定为1000),然后赋给当前要保存的对象A,当执行inser 语句时,就触发了before insert触发器,重新从sequence中获取了主键值(1001),导致当前保存对象的主键是1001,但是在代码中对象A的ID仍然是1000,所以在保存中间表数据时,会说破坏了外键约束。的确数据库中没有主键值为1000的记录。

 

备注1.

如果使用hibernate作为中间件,那么在数据库中就不要创建before insert触发器来获取NEW.ID。在*.hbm.xml中指定库表主键所使用的sequence。

备注2.

抛开hibernate不谈,如果创建了before insert触发器,那么就建立了一个库表和sequence之间的一个联系,我们使用SQL命令插入数据的时候就不需要考虑ID的值了。

insert into stock(code,name) values(‘code’,’name’);

备注3.

如果没有创建before insert触发器,那么库表的主键要使用一个sequence,必须在SQL命令中指定主键的值。insert into table1 values(sequence_name.curval,’code’,’name’);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值