0

我對Spring和Hibernate以及延遲加載有一些困難。有很多問題和答案,但不是我真正想要的。Hibernate Spring JPA只加載特定的懶惰關係

因此,讓我們說我有一個Car類。與id,name以及與doors,windowswheels的一對多關係。因爲他們是oneToMany,他們是默認的懶加載這是首選,因爲當我想查看名稱car我不想看到輪胎和東西。這適用於我的情況,使用我的存儲庫的默認findOne()方法。

但是當我想查看輪胎壓力時,我需要初始化tires關係。我曾經這樣做過Hibernate.initialize(car.getTires())。這會爲數據庫生成另一個SELECT查詢。現在我想改進我的數據庫查詢,並選擇與tires,但省略了windowsdoors。 (這可以在MySQL中使用連接)。讓他們加載的選項是沒有問題的,因爲我不總是想加載tires關係(我在我的對象上有一些很大的關係)。

我嘗試以下方法:

@Query("SELECT c FROM Car c JOIN FETCH c.tires WHERE c.id = :id") 
Car findOneWithTiresLoaded(@Param("id") Long id); 

這並提供正確的數據。但是在分析了從存儲庫返回的對象之後,我注意到所有的關係都被加載了。因此,這不僅會返回cartires的關係,還會返回doorswindows。 下面給我相同的輸出(與moneToMany關係加載)

@Query("SELECT c FROM Car c WHERE id = :id") 
Car findOneWithTiresLoaded(@Param("id") Long id); 

東西是不是想要的。我預計這隻會輸出Car對象而沒有所有懶惰的關係。

互聯網上的人也建議打電話Car.getTires().size()。這也會產生另一個SELECT查詢。

有沒有什麼辦法只選擇Car而只裝載Tires關係?沒有fetch = FetchType.LAZY,Hibernate.initialize()size()方法?如何加入一張桌子不可能?另外,我不使用XML進行任何配置。

謝謝!

回答

1

我總是建議使用實體圖來實現這個。我將使用Spring Data給出一個例子。無論如何,總是應該使用延遲加載,所有其他關係可以使用特定的圖形連接。

通過這種方式,您可以對您的查詢非常具體,只需獲取業務邏輯所需的數據。您甚至可以定義子圖來顯示您想從tires實體中選擇的內容。這意味着你總是懶得提取所有的Tire實體關係。默認情況下,你所得到的是tires(按要求)並且沒有其他關係。如果您還需要tires中的其他內容,那麼您只需要在其中定義另一組圖形定義,並從存儲庫中引用它們,並將查詢作爲子圖形進行查詢。

@Entity 
@Table(name = "car") 
@NamedEntityGraph(name = Car.TIRES_GRAPH, attributeNodes = @NamedAttributeNode("tires")) 
public class Car { 

    public static final String TIRES_GRAPH = "Car.tires"; 

    @OneToMany(mappedBy = "car", fetch = FetchType.LAZY} 
    private Set<Tire> tires = new HashSet<>(); 

} 

併爲您的存儲庫,你可以有一個方法

@Query("SELECT c FROM Car c") 
@EntityGraph(Car.TIRES_GRAPH) 
Set<Car> findAllWithTires(); 

即使你不使用Spring的數據,那麼該方法是一樣的,你可以很容易地找到好例子。

EDIT

另一個測試工作示例。只要確保您的字段名稱與Spring數據的域匹配即可解決它們。

public interface CarRepository extends JpaRepository<Car, Long> { 

    @EntityGraph(attributePaths = { "tires" }) 
    Set<Car> findAllWithTiresByCarId(Long id) 
} 

Link到文檔

+0

我是否需要用'@ Table'進行註解的實體?因爲我們現在不這樣做,如果它不需要,它會更清潔,而不是寫它。還是用於對象圖?我現在就試試這個。如果這對我們有用,我會將您的答案標記爲解決方案。謝謝回覆! – Clemenz

+0

不能將'@ Table'省略,我只是習慣用它來定義實體。 – Vaelyr

+0

我剛剛發現'Car'類擴展了一個'Vehicle'類。所以它使用'@ Inheritance'註解。 (也是@ @ DiscriminatorValue('car')註釋)。當我嘗試在'Car'實體中使用命名圖時,它在啓動時給我一個錯誤。 '無法使用此ManagedType [com.example.domain.Vehicle]'上的給定名稱[Tires]定位屬性。但是我查詢'Car'庫中的'Car'表。什麼會造成這種情況? – Clemenz