簡體   English   中英

僅從 class 層次結構中檢索超類

[英]Retrieve only the superclass from a class hierarchy

我有一個場景如下:

@Entity
@Table(name = "ANIMAL")
@Inheritance(strategy = InheritanceType.JOINED)

public class Animal implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "S_ANIMAL")
    @SequenceGenerator(name = "S_ANIMAL", sequenceName = "S_ANIMAL", allocationSize = 1)
    public int getNumero() {
        return numero;
    }

    public void setNumero(int numero) {
        this.numero = numero;
    }
        .
        .
        .
}

並作為子類:

@Entity
@Table(name = "DOG")
public class Dog extends Animal {

    private static final long serialVersionUID = -7341592543130659641L;
        .
        .
        .
}

我有這樣的 JPA Select 語句:

SELECT a FROM Animal a;

我正在使用 Hibernate 3.3.1

正如我所看到的,框架使用左外連接檢索AnimalDog的實例。

有沒有辦法 Select 只有“部分” Animal 我的意思是,之前的Select將獲得所有的Animal ,那些只是Animal而不是Dog的,以及那些是Dog的。

我想要它們,但對於Dog的情況,我只想檢索它們的“動物部分”。

我找到了@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT)但我可以看到這只有在 Animal 不是@Entity時才有效。

非常感謝。

簡短回答:您描述的行為符合JPA標准。 沒有JPA標准方法來限制JPA提供程序僅檢索超類。

提供者可以選擇查詢實現邏輯來實現功能,一致性和性能。 只要它尊重您的實體注釋並在查詢中返回所請求的信息,一切都很好。 將Dog的外部聯接視為私有實現細節,不應該與您有關。 提供程序已編寫外部聯接以協助性能和一致性。

考慮:

  • JPA被定義為處理java對象實體而不是表
  • 您的實體層次結構Root的根不是抽象的,因此您可以創建實例並將其保留。
  • 您有一個Animal @DescriminatorColumn和@DescriminatorType的默認值 - 因此Animal表將添加一個名為“DTYPE”的標識符列並鍵入“some String type”。 您有@DescriminatorValue的默認值 - 將等於實體名稱:Animal。 創建此實體時,Animal.DTYPE column =“Animal”。
  • 實體狗有一個超類動物。 默認值也用於其@DescriminatorValue - Dog。 因此,當您創建此實體時,Animal.DTYPE column =“Dog”。
  • Java類限制確保每當Dog對象存在時,也存在相應的Animal超類對象。
  • 通常,當您將實體動物加載到JPA持久性上下文中時,使用@DescriminatorValue(值存儲在DTYPE列中)=“Dog”,然后將Dog對象加載到PC中以保持一致性非常有用。 即使JPA標准不要求它。
  • 繼承關系不能指定為EAGER或LAZY(如基本類型字段或實體關系字段)。 如果你需要讀取/更新狗屬性並且沒有加載Dog類,你會怎么做? 運行單獨的查詢來重新加載它? 這會大大損害一致性和性能。
  • 性能的主要關注點是發送到DB的單獨SQL命令的總數。
    在時間方面:與動物表的查詢僅比動物外部加入狗的查詢稍微快一點(10微秒???),但比兩個單獨的查詢(一個用於動物,一個用於狗)快得多

實際上,有一種方法可以獲得超類:您只需要使用JPA的本機查詢。 就我而言,我正在使用JPA存儲庫。 因此,它會是這樣的:

@Query(value = "SELECT * FROM animal", nativeQuery = true)
List<Resource> findAllAnimal();

標志nativeQuery為true允許在數據庫上運行本機SQL。

如果您使用的是Entity Manager,請查看以下內容: https//www.thoughts-on-java.org/jpa-native-queries/

Hibernate 使用屬性“clazz_”來確定子類。

例子:

select 
  animal0_.animal_id as animal_i1_0_,..., 
  case 
    when animal0_1_.animal_id is not null then 1 
    when animal0_2_.animal_id is not null then 2 
    when animal0_.animal_id is not null then 0 
  end as clazz_
from animal animal0_ 
left outer join dog animal0_1_ on animal0_.animal_id=animal0_1_.animal_id
left outer join cat animal0_2_ on animal0_.animal_id=animal0_2_.animal_id

您應該使用“ 0 AS clazz_ ”指定 SQL

@Query(value = "SELECT *, 0 AS clazz_ FROM animal", nativeQuery = true)
List<Animal> findAllAnimal();

暫無
暫無

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

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