问题描述
我们在使用 EclipseLink JPA 在 H2 数据库中的单个事务中插入两个表时遇到问题。
数据库架构看起来像…… 表 A {...,IP_ADDRESS Varchar2( 15 ) 不为空 }
表 B {...,IP_ADDRESS Varchar2( 15 ) 不为空,
约束 MY_FK 外键 (IP_ADDRESS) 引用 A
}
我们遇到的问题是 B 上的外键约束使事务失败。
我们正在这样做:
entityManager.getTransaction().begin();
entityManager.merge(保存到一个事务); entityManager.merge(保存到B事务);
entityManager.getTransaction().commit();
看起来 JPA 试图先保存到 B 并且失败了。 或者它可能首先检查 B 上的约束?
无论如何,我们想要做的理想情况就像我多年前回忆的那样,在 oracle 上使用 PL/SQL:
BEGIN
Do the insert on A;
Do the insert on B;
commit;
End;
我认为 Oracle 在事务完成之前不会查看约束。或者因为事务的未提交版本没有违反约束而允许它完成。
有什么想法吗?我查看了文档,但还没有找到任何有用的东西。
谢谢
解决方法
我相信我已经发现了问题,尽管我希望得到比我更了解 JPA 的人的确认。 这里的问题是在代表两个表的实体类中没有定义外键约束。
因此,EntityManager 对两个表之间的关系一无所知,并选择了任意插入顺序。 然后事务失败,因为 JPA 试图在表 A 的行之前插入表 B 的行。
我通过在表 B 和 @OneToMany 关系表 A 中添加一个@ManyToOne 关系来解决这个问题。我将获取类型设置为惰性作为关系定义,因为不需要使用任何获取结果。
在A表实体类中:
// bi-directional one-to-many association to PositionHostPermission
@OneToMany( mappedBy = "the a entity",fetch=FetchType.LAZY )
private Set<B> bInstances;
在表 B 实体类中:
//bi-directional many-to-one association to ipAddress
@ManyToOne( fetch= FetchType.LAZY )
@JoinColumn(name="IP_ADDRESS",insertable=false,updatable=false )
private A aTableInstance;