簡體   English   中英

如何使 Spring (Hibernate) 將單個表 inheritance 場景中的子實體實例化為它們的代理而不是基本實體代理?

[英]How to make Spring (Hibernate) instantiate child entities in single table inheritance scenario as their proxies instead of base entity proxy?

最近我開始收到 Hibernate 的HHH000179: Narrowing proxy to class警告,當我試圖刪除包含其他關系的子實體(繼承)時。

這讓我了解到 Hibernate 代理是為每個實體單獨創建的,即使這樣的實體是一個抽象的基礎實體(不是@MappedSuperclass ,而是abstract @Entity )——即使基礎實體 class 永遠不會單獨存在。

考慮屬性的結構:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(...)
public abstract class Attribute { ...ids and common fields... }

@Entity
@DiscriminatorValue("V")
public class AttributeValued extends Attribute
{
    @OneToMany( mappedBy = "attribute",
                cascade = CascadeType.ALL,
                orphanRemoval = true)
    private Set<Value> values = new LinkedHashSet<>();
}

使用 Spring JPA 我有存儲庫,例如:

interface AttributeRepository extends JpaRepository<Attribute, Long> {}

考慮給定一些已知屬於AttributeValued類型的 id 我運行這個:

Attribute a = this.attributeRepository.getReferenceById(id);
if (a instanceof AttributeValued)
{
    System.out.println("VALUED");
}
else
{
    System.out.println("OTHER");
}

這會打印“OTHER”,而我希望它打印 VALUED。 這意味着 Spring/Hibernate 將#getReferenceById實例化為基礎 class Attribute (或者更確切地說,它是 Hibernate 代理)。

有沒有辦法讓 Spring/Hibernate 在使用通用JpaRepository<Attribute>時返回實際實體( AttributeValued )的代理?

由於這種行為,如果我這樣做:

// id is known to be of type AttributeValued
Attribute a = this.attributeRepository.getReferenceById(id);
this.attributeRepository.delete(a);

Hibernate 用HHH000179: Narrowing proxy to class AttributeValued因為變量aAttribute的代理,而delete(a)將創建與AttributeValued代理相同行的另一個表示,因為AttributeValued.values關系具有:

cascade = CascadeType.ALL
orphanRemoval = true

所以現在我有Attribute AttributeValued代理(我認為)。

您可以在子實體上使用 @Embedded 注釋,這樣子實體和父實體將在數據庫中形成一個表您可以在官方文檔https://www.baeldung.com/jpa-embedded-embeddable中閱讀更多相關信息

好的,所以問題絕對出乎我的意料。

#getReferenceByIdJpaRepository方法。

我在整個項目中基本上到處都使用它(因為 Hibernate 是 Jpa,我認為這是正確的方法)。

事實證明,由於某種原因,使用它進行查詢不是多態的,並且返回Attribute的代理,即使已知 row 表示AttributeValued (使用@DiscriminatorValue("V") )。

#findById(id)是一個CrudRepository方法,它實際上是多態的並返回AttributeValued的代理,因此當我稍后使用#delete(id)時,我不會遇到像原始問題那樣的問題(同一行的兩個代理和警告HHH000179: Narrowing proxy to class )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM