除非访问集合,否则休眠的OneToMany FetchType.LAZY无法工作吗?

sea*_*est 4 java spring hibernate one-to-many

我正在使用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;
...
}
Run Code Online (Sandbox Code Playgroud)

我有一个MarketInfo,我希望当我调用它的getChannelGroups()方法时,它将返回List,但是在这种情况下,我可以看到未触发HQL查询,看来我们必须访问该List中的某些项才能触发HQL查询,否则MarketInfo的channelGroups为null。

情况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
Run Code Online (Sandbox Code Playgroud)

情况2:

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

// here market's channelGroups is empty
Run Code Online (Sandbox Code Playgroud)

情况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
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙解释一下吗?

uju*_*ulu 5

market.getChannelGroups(); //这不起作用,市场的channelGroups仍然为空。

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

market.getChannelGroups().size();
Run Code Online (Sandbox Code Playgroud)

现在,为什么以下通话有效?

System.out.println(market.getChannelGroups());
Run Code Online (Sandbox Code Playgroud)

如果您了解System.out.println()其工作原理,那么原因就很清楚了,也就是说,它正在toString()传入的对象上调用方法,在这种情况下,该方法等效于以下内容:

System.out.println(market.getChannelGroups().toString());
Run Code Online (Sandbox Code Playgroud)

这是该println(Object)方法的JavaDoc :

打印一个对象,然后终止该行。此方法首先调用String.valueOf(x)来获取打印对象的字符串值,然后像先调用print(String)然后再调用println()一样操作。