除非访问集合,否则 Hibernate OneToMany FetchType.LAZY 无法正常工作?

Hibernate OneToMany FetchType.LAZY is not working unless accessing the collection?

我正在使用 spring 4.1.4.RELEASE + hibernate 4.3.6.Final,这是我的实体代码:

public class BaseEntity implements Serializable {
}

public class MarketInfo extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private int id;

    @Column(name = "market_id", unique = true, length = 15)
    private String marketId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "market")
    private List<MarketChannelGroup> channelGroups;

    public List<MarketChannelGroup> getChannelGroups() {
        return channelGroups;
    }

    public void setChannelGroups(List<MarketChannelGroup> channelGroups) {
        this.channelGroups = channelGroups;
    }

...
}

public class MarketChannelGroup extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private int id;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "market_id", referencedColumnName = "market_id")
    private MarketInfo market;
...
}

我有一个 MarketInfo,我希望当我调用它的 getChannelGroups() 方法时,它会 return 列表,但是我可以看到在这种情况下没有触发 HQL 查询,看来我们必须访问该列表中的某些项目触发 HQL 查询,否则,MarketInfo 的 channelGroups 为空。

案例 1:

System.out.println(market.getChannelGroups()); // this is working, market's channelGroups is not empty. HQL query is triggered.

// here market's channelGroups is not empty

案例二:

market.getChannelGroups(); // this is not working, market's channelGroups is still empty.HQL query is not triggered.

// here market's channelGroups is empty

案例 3:

market.getIndexes().get(0).getDate(); // this is working, market's channelGroups is not empty. HQL query is triggered.

// here market's channelGroups is not empty

谁能帮忙解释一下?

market.getChannelGroups(); // this is not working, market's channelGroups is still empty.

发生这种情况的原因可能是 market.getChannelGroups() 调用由于延迟加载而返回 proxy。当您在返回的对象上调用方法时,将发生实际加载,在本例中是通道组集合。 因此,要触发将实体加载到集合中,您必须调用以下命令,例如:

market.getChannelGroups().size();

为什么下面的调用有效?

System.out.println(market.getChannelGroups());

如果您了解 System.out.println() 是如何工作的,原因就会很清楚,即它正在调用传入对象的 toString() 方法,在这种情况下等同于以下内容:

System.out.println(market.getChannelGroups().toString());

这是 println(Object) 方法的 JavaDoc:

Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().