休眠惰性加载不';在java 11中不能使用forEach()

休眠惰性加载不';在java 11中不能使用forEach(),java,hibernate,spring-data-jpa,java-11,Java,Hibernate,Spring Data Jpa,Java 11,我不知道哪里有人报告java bug。老实说,我以前从未见过。但是HibernateJPA和JavaForeach的延迟加载在Java11.0.2中不起作用。我没有看到它在11.0.3中被列为已修复,但没有进行测试 它在Java8中工作。所以我想买主要当心了 框架: 弹簧护套2.1.1(弹簧5.1.3) Hibernate 5.3.7.1最终版本 开始编辑 部分父模型: @Entity @Table(name = "REST_ENDPOINT") public class RestEndpoin

我不知道哪里有人报告java bug。老实说,我以前从未见过。但是HibernateJPA和JavaForeach的延迟加载在Java11.0.2中不起作用。我没有看到它在11.0.3中被列为已修复,但没有进行测试

它在Java8中工作。所以我想买主要当心了

框架: 弹簧护套2.1.1(弹簧5.1.3) Hibernate 5.3.7.1最终版本

开始编辑 部分父模型:

@Entity
@Table(name = "REST_ENDPOINT")
public class RestEndpoint extends AuditModel {
    private String  endpointName;
    private String  httpVerb;
    private String  httpTemplate;
    private String  serviceName;
    ...
    @OneToMany(mappedBy = "restEndpoint", cascade = CascadeType.ALL, orphanRemoval = true)
public List<RestEndpointParam> params = new ArrayList<>();

public void addRestEndpointParam(RestEndpointParam param) {
    params.add(param);
    param.setRestEndpoint(this);
}

public void removeRestEndpointParam(RestEndpointParam param) {
    params.remove(param);
    param.setRestEndpoint(null);
}

public void setParams(List<RestEndpointParam> params) { this.params = params; }

public List<RestEndpointParam> paramsList() {
    return params;
}
现在来看可怕的部分。子表中有两个项,第一个foreach甚至不打印log语句

    // First set up the URI replacement variables    
    restEndpoint.paramsList().forEach(restEndpointParam -> {
        logger.warn("ENDPOINT 1st forEach access PARAM:{}", restEndpointParam.getType());
        if (restEndpointParam.getType().equals("URI")) {
            uriParams.put(restEndpointParam.getKey(), restEndpointParam.getValue());
    }});

// Now apply the Query parameters
    restEndpoint.paramsList().forEach(restEndpointParam -> {
        logger.warn("ENDPOINT 2nd foreach access PARAM:{}", restEndpointParam.getType());
        if (restEndpointParam.getType().equals("QUERY")) {
            builder.queryParam(restEndpointParam.getKey(), restEndpointParam.getValue());
    }});
第二个forEach按预期工作。因此,这是第一个失败的引用。还将第一次访问(forEach)替换为常规环路:

for (RestEndpointParam restEndpointParam : restEndpoint.paramsList())

结果如预期。因此,显然hibernate和Java 11之间存在加载问题。

我不知道为什么Java 8可以这样做,或者为什么第二个
foreach
可以这样做

但是
paramsList()
正在直接访问字段
params
。Hibernate将延迟加载附加到getter,但由于没有getter,所以这不起作用


如果将
paramsList()
重命名为
getParams()
Hibernate,则应将其检测为getter并执行propper延迟加载。

如果第二个
restedpoint.paramsList().forEach
有效,但第一个无效,则逻辑假设问题在于第一个
forEach
。但是如果没有追踪和解释,很难判断是什么“不起作用”的意思是……您是否尝试在Iterable的forEach方法中设置断点?我确实设置了断点。实际上,这就是我添加log语句的原因。在第一种情况下,根本不执行lamba。在IntelliJ中,我可以看到parmlist有两个条目。但我唯一的解释是,它的计算结果为size()==0——或者更可能为null。否则应执行forEach。请发布代码或
paramsList()
。我猜您正在访问其中的
params
,这可以解释为什么它会被破坏,因为您实际上是在侧步执行JPAs延迟加载。@Jens Schauder我添加了显示如何映射子表的整个部分。我承认我在这方面有一些问题,所以这可能不是“正确的方式”。但它在Java8中确实可以工作。“互联网记住一切”的负面影响是,7年不起作用的东西是谷歌点击量的前10页。这么好;工作现代的;像这样的代码很难找到。TBH我不知道JPA延迟加载是如何在这里被忽略的。Hibernate使用
PersistentList
s初始化延迟获取的列表,
PersistentList
本身负责在首次访问时加载数据。您只需要对
@OneToOne
的反向可选端进行getter,而不是对多值关联进行getter。听起来我为我的另一个问题找到的解决方案是什么导致了这一点。但是对于我的结构,我不能仅仅将parmsList更改为getParams,因为这样我会得到一个错误,即Hibernate SessionFactory无法确定列表的类型。如果您能回顾一下我上一期的文章,可能会很有启发性(也很幽默)
for (RestEndpointParam restEndpointParam : restEndpoint.paramsList())