跳至主要内容

Dev's Ranting - Hibernate Mapping Collections of Subtypes

Hibernate 作为ORM框架的中流砥柱被广泛地应用于企业应用程序开发中。从早期的XML配置到现在的Java Configuration,开发者早已习惯了使用各种 annotation 来配置 entity mapping。不过基础概念都是一样的。 为了展示用于一对多关系的多表映射,DZone上有一个[挺简单的例子](https://dzone.com/tutorials/java/hibernate/hibernate-example/hibernate-mapping-one-to-many-using-annotations-1.html)。 @Entity @Table(name = "STUDENT") public class Student { private long studentId; private String studentName; private Set studentPhoneNumbers = new HashSet(0); @OneToMany(cascade = CascadeType.ALL) @JoinTable(name = "STUDENT_PHONE", joinColumns = { @JoinColumn(name = "STUDENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "PHONE_ID") }) public Set getStudentPhoneNumbers() { return this.studentPhoneNumbers; } } 这两天遇到了一个定义映射关系的问题,与上面这个映射的区别在于,除了 Entity A 和 B 之间有 join table之外,Entity B 实际上是共享一个table的sub type,使用了 `@DiscriminatorColumn` 和 `@DiscriminatorValue` 来定义 parent (abstract) type 和 subtype。 如果仅仅使用向上例代码中的定义,Hibernate生成的SQL仅仅执行多表连接,并不会过滤特定的 discriminator 类型。有一位同事建议尝试 `@DiscriminatorOptions(force = true)` 强迫 Hibernate 在加载的时候执行类型校验,但是无效。怀疑与join table的存在有关? 古老的XML配置可以指定 formula 但是现在的 `@Formula` 演变成为了动态计算的 virtual column,也无用。 后来又看见有人说可以使用 Hibernate 自家的 annotation `@Loader` 来提供一个named query以取代自动生成的SQL,尝试未遂,皆因自定义的quer还需要pass一个(或多个)参数,而没有任何文档告诉如何实现。 难道真的就木有办法了吗……??后来发现,还是有办法的— `@Where(clause = "disc_type = 'subtype_disc_value'")` 这个注释使得Hibernate在生成SQL的时候会加入指定的WHERE子句,而这个子句恰恰是用于限定 `DiscriminatorColumn`的。

评论