简体   繁体   中英

Hibernate reloading entities in a fetch join

I am having a problem with Hibernate reloading the entities in a query even though they are being fetched as part of the main query.

The entities are as follows (simplified)

class Data {
    @Id
    String guid;

    @ManyToOne(fetch = FetchType.LAZY)
    @NotFound(action = NotFoundAction.IGNORE)
    DataContents contents; 
}

class DataClosure {
    @Id
    @ManyToOne(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "ancestor_id", nullable = false)
    private Data ancestor;

    @Id
    @ManyToOne(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "descendant_id", nullable = false)
    private Data descendant;

    private int length;
}

This is modelling a closure table of parent / child relationships.

I have set up some criteria as follows

    final Criteria criteria = getSession()
            .createCriteria(DataClosure.class, "dc");
    criteria.createAlias("dc", "a");
    criteria.createAlias("dc.descendant", "d");
    criteria.setFetchMode("a", FetchMode.JOIN);
    criteria.setFetchMode("d", FetchMode.JOIN);
    criteria.add(Restrictions.eq("d.metadataGuid",guidParameter));
    criteria.add(Restrictions.ne("a.metadataGuid",guidParameter));

This results in the following SQL query

select
    this_.descendant_id as descenda2_21_2_,
    this_.ancestor_id as ancestor3_21_2_,
    this_.length as length1_21_2_,
    d2_.guid as metadata1_20_0_,
    d2_.name as name5_20_0_,
    a1_.guid as metadata1_20_1_,
    a1_.name as name6_20_1_
from
    data_closure this_ 
inner join
    data d2_ 
        on this_.descendant_id=d2_.metadata_guid 
inner join
    data a1_ 
        on this_.ancestor_id=a1_.metadata_guid 
where
    d2_.guid=? 
    and a1_.guid<>?

which looks like it is correctly implementing the join fetch. However when I execute

    List list = criteria.list();

I see one of these entries in the SQL log per row in the result set

Result set row: 0
DEBUG Loader  - Loading entity: [Data#testGuid19]
DEBUG SQL  - 
select
    data0_.guid as guid1_20_0_,
    data0_.title as title5_20_0_,
from
    data data0_ 
where
    data0_.guid=?
Hibernate: 
   (omitted)
DEBUG Loader  - Result set row: 0
DEBUG Loader  - Result row: EntityKey[Data#testGuid19]
DEBUG TwoPhaseLoad  - Resolving associations for [Data#testGuid19]
DEBUG Loader  - Loading entity: [DataContents#7F1134F890A446BBB47F3EB64C1CF668]
DEBUG SQL  - 
select
    dataContents0_.guid as guid_12_0_,
    dataContents0_.isoCreationDate as isoCreat2_12_0_,
from
    dataContents dataContents0_ 
where
    dataContents0_.guid=?
Hibernate: 
    (omitted)

It is looks like even though the DataContents is marked as lazily loaded, it's being loaded eagerly.

So I either want some way in my query to fetch join DataClosure and Data and lazily fetch DataContents, or to fetch join the DataContents if that is not possible.

Edit:

Modelling the closure table like this

class DataClosure {
    @Id
    @Column(name = "ancestor_id", nullable = false, length =36 )
    private String ancestorId;

    @Id
    @Column(name = "descendant_id", nullable = false, length =36 )
    private String descendantId;

    @ManyToOne(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "ancestor_id", nullable = false)
    private Data ancestor;

    @ManyToOne(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "descendant_id", nullable = false)
    private Data descendant;

    private int length;
}

fixed the problem. In other words, having @Id annotation on entities from other tables seemed to cause the issue, even though there was nothing wrong with the queries generated.

I think your problem here might be this

@NotFound(action = NotFoundAction.IGNORE)

There are plenty of google results where using that causes the lazy loading to become eager. I think it is a bug in Hibernate.

Adding this to the list of annotations should fix the problem

@LazyToOne(value=LazyToOneOption.NO_PROXY)

Since that informs Hibernate that you will not try to use that property later on so no proxy is required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM