簡體   English   中英

Hibernate,在不加載關聯實體的情況下獲取外部id

[英]Hibernate, get foreign id without loading associated entity

簡單的例子:

映射:

@Entity
public class City {
    @Id@GeneratedValue
    private Integer id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    private Country country;
...


@Entity
public class Country {
    @Id@GeneratedValue
    private Integer id;

    private String name;
...

用法:

Query query = session.createQuery("from City");
List<?> cities = query.list();
for (Object cityObj : cities) {
    City city = (City) cityObj;
    System.out.printf("City: %s %s%n", city.getId(), city.getName());
    Country country = city.getCountry();
    System.out.println("Country retrieved");
    Integer countryId = country.getId();
    System.out.printf("Country id: %s%n", countryId);
}

這是輸出:

Hibernate: select city0_.id as id0_, city0_.country_id as country3_0_, city0_.name as name0_ from City city0_
City: 1 Astana
Country retrieved
Hibernate: select country0_.id as id1_0_, country0_.name as name1_0_ from Country country0_ where country0_.id=?
Country id: 1
City: 2 Almaty
Country retrieved
Country id: 1
City: 3 Omsk
Country retrieved
Hibernate: select country0_.id as id1_0_, country0_.name as name1_0_ from Country country0_ where country0_.id=?
Country id: 2

現在這是一種奇怪的行為。 我可以獲得Country對象(可能是一些代理),Hibernate還沒有發出任何額外的SQL查詢。 但是當我調用country.getId()時 - hibernate會發出SQL查詢來加載完整的國家/地區對象。 很明顯,Hibernate知道country.id值,所以我希望hibernate只返回該id而不需要任何額外的SQL查詢。 但事實並非如此。

問題是 - 我不需要整個實體。 我只需要id,我不需要單獨的SQL查詢(如果我設置FetchType.EAGER,則不需要JOIN查詢)。

我認為你必須像下面AccessType改變你的Country實體。在Id字段上添加AccessType注釋。

@Entity
    public class Country {
        @Id@GeneratedValue@AccessType("property")
        private Integer id;

        private String name;

面對類似的問題,並按照這篇文章: - 訪問者類型注釋

所以正確的JPA標准解決方案將是:

@Entity
public class Country {

    @Id @GeneratedValue @Access(PROPERTY)
    private Integer id;

只是想加入@ RE350的答案。

在Hibernate 5.2.15中,如果您使用的是CriteriaQuery 然后,這可以很容易地完成,而不需要@AccessType注釋。(已經棄用了@AttributeAccessor )。

final CriteriaBuilder cb = criteriaBuilder();
final CriteriaQuery<City> query = criteriaQuery();

final Root<City> q = query.from(City.class);
final Path<Integer> uid = q.get("country").get("id"); // Note this!!

注意 :您也可以像這樣獲取國家/地區,在這種情況下,它實際上會加入表格。

final Path<Integer> uid = q.join("country").get("id");

更新:

但是,對於ManyToMany連接,這似乎並不容易,除非您有一個實體來為ManyToMany表建模。

暫無
暫無

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

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