如何使用纯JPA / Hibernate注释避免外键约束违规

时间:2014-08-05 12:34:11

标签: java hibernate jpa foreign-keys hsqldb

我正在研究我的数据库模型问题一段时间了。我使用 Hibernate 来管理我的实体,整个事情存储在 HSQLDB(内存数据库)中,因此这些表是在运行时由hibernate创建的。我的注释类的一个简短示例如下所示:

@Entity
@Table(name = "Paper")
public class Paper {
  @Id
  @Column(name = "ID")
  private Long id;

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "Paper_Ref", joinColumns = { @JoinColumn(name = "SrcID") }, inverseJoinColumns = { @JoinColumn(name = "DstID") })
  private Set<Paper> references = new HashSet<Paper>();
}

@Entity
@Table(name = "Paper_Ref")
public class PaperRef
{
  @Id
  private Long id;

  @Column(name = "SrcID")
  private Long srcId;

  @Column(name = "DstID")
  private Long dstId;
}

如您所见,一篇论文链接到其他几篇论文,相应的关系存储在一个名为Paper_Ref的表中。 SrcID和DstID对Paper的主键具有外键特性。但是,已解决的主键不一定存在于我的数据库中。

整个工作正常,但如果数据中存在一些不一致(例如在添加相应的论文之前添加纸张参考),我会遇到外键约束违规。此外,我实际上无法手动控制这些不一致,因为我从另一个没有任何约束的源接收数据。

通常这就是每个人都希望这种关系能够发挥作用的方式,但我正在寻找一种避免违规的方法,或者只是忽略它。例如,通过手动删除约束。

我自己的解决方法是形成一个本机查询,如下所示:

SELECT p FROM Paper AS p WHERE p.id IN (SELECT pr.dstId FROM PaperRef pr WHERE srcId = :id)

但我更喜欢使用原生的hibernate解决方案,我可以在不使用自制查询的情况下为我的论文集调用getter。

有没有办法删除/禁用外键约束或另一种方法来解决这个问题?或者是对我的休眠关系如何工作的误解呢?

提前致谢!

1 个答案:

答案 0 :(得分:0)

我想我现在确实解决了这个问题。感谢所有读者和贡献者。 HSQLDB 提供了在运行时禁用外键检查的选项。 SQL语句如下:

SET DATABASE REFERENTIAL INTEGRITY FALSE;

关闭此功能还有其他后果,HSQLDB Docs中也有注明。 Hibernate不再跟踪数据库所做的更改,因此如果没有进一步的操作,将返回关系(Subselects)的不完整结果。要解决此问题,必须为可能已分离的每个对象调用EntityManager.refresh()

我只是使用内存数据库来获取连接功能,因为外部服务没有提供这样的功能。我之后删除了实体,所以对我来说这不是一个大缺点。

快乐的编码!