休眠延迟加载不适用于Java 11中的forEach()

时间:2019-05-23 13:00:16

标签: java hibernate spring-data-jpa java-11

我不知道在哪里报告Java错误。老实说,我从未见过。但是休眠的JPA和Java foreach的延迟加载在Java 11.0.2中不起作用。我没有看到它在11.0.3中被列为固定版本,但是没有进行测试。

它在Java 8中确实有效。因此,我想买家要当心!

框架: Spring Boot 2.1.1(Spring 5.1.3) Hibernate 5.3.7.Final

开始编辑 部分父模型:

@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;
}

END EDIT

子表:

@Entity
@Table(name = "REST_ENDPOINT_PARAM")
public class RestEndpointParam {
...
private Long endpointId;
private RestEndpoint restEndpoint;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ENDPOINT_ID", insertable = false, updatable = false)
public RestEndpoint getRestEndpoint() { return restEndpoint; }

现在是最恐怖的部分。子表中有2个项目,第一个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())

结果符合预期。因此很明显,休眠和Java 11之间存在加载问题。

1 个答案:

答案 0 :(得分:0)

我不知道为什么它可以与Java 8一起使用,或者为什么第二个foreach可以工作。

但是paramsList()正在直接访问字段params。 Hibernate将延迟加载附加到getter上,但是由于没有getter,这是行不通的。

如果将paramsList()重命名为getParams(),Hibernate应该将其检测为吸气剂并执行适当的延迟加载。