搜索从@MappedSuperclass 扩展的所有表

search though all tables extended from @MappedSuperclass

我在搜索从@MappedSuperclass 扩展的实体时遇到了问题。我创建了一个 class PhoneBook 并从中扩展了 2 个实体:FirstPhoneBook 和 SecondPhoneBook。结构如下所示:

@MappedSuperclass
public abstract class PhoneBook {
...

@Entity
@Table(name = "first_phone_book")
public class FirstPhoneBook extends PhoneBook {
...

@Entity
@Table(name = "second_phone_book")
public class SecondPhoneBook extends PhoneBook {
...

这些table绝对相似。我描述了 PhoneBook class 中的所有字段,childs 中只有默认构造函数。外部系统发送一个 phone 数字作为参数。根据 table 是否包含这样的数字,我的系统会用一个词进行响应。

问题是:如何在不对每个子 class 名称进行硬编码的情况下,在从 @MappedSuperclass 扩展的每个 table 中单独搜索?

我只能找到这样的按值搜索的变体:

currentSession.get(Employee.class, theId);

但是有对实体 class 的显式调用。我希望它是可扩展的,而不需要为每个添加的新实体编写新的 DAO。当前方法签名如下所示:

public <T extends PhoneBook> T findByNumber(String number);

您描述的是多态查询,即引用父项的查询 class。 Hibernate documentation 表示在使用 @MappedSuperclass 继承时没有得到很好的支持:

Because the @MappedSuperclass inheritance model is not mirrored at the database level, it’s not possible to use polymorphic queries referencing the @MappedSuperclass when fetching persistent objects by their base class.

如果经常使用多态查询,最好使用table per class继承策略:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class PhoneBook {
...

@Entity
@Table(name = "first_phone_book")
public class FirstPhoneBook extends PhoneBook {
...

@Entity
@Table(name = "second_phone_book")
public class SecondPhoneBook extends PhoneBook {
...

然后您可以使用 superclass:

获取实体
PhoneBook phoneBook = currentSession.get(PhoneBook.class, theId);

和 Hibernate 通常会使用 UNION 来对两个 table 进行查询。

这就是说,即使使用 @MapperSuperclass,Hibernate 仍然可以查询所有 table 以查找扩展父 class 的 class。您可以使用以下 JPA 查询(请注意,它使用父 class 的完全限定 class 名称):

Query<PhoneBook> query = currentSession.createQuery("from " + PhoneBook.class.getName() +
                                                    " where id = :id", PhoneBook.class);
query.setParameter("id", theId);

不同之处在于这里它不是查询实体,而是查询扩展父 class 的所有 classes。同样在这种情况下,与 table-per-class 策略不同,Hibernate 不会使用 UNION,而是向每个 table 发送一个查询,在这种情况下是两个单独的 SQL 查询而不是一个。