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`的。
评论