JPA懒惰列表上的流

我有这样的列表的JPA实体:

@OneToMany(mappedBy = "scadaElement", orphanRemoval = true) private List elementParameters; 

和地图formsElementParameter

 @ManyToOne @JoinColumn(name = "SCADAELEMENT_ID") ScadaElement scadaElement; 

当我获得带有elementParameters列表的实体并在其上执行流时,什么都不做,即使我使用.size()触发列表但是当我使用for循环执行相同操作时。

 System.out.println("elements size: " + s.getElementParameters().size()); s.getElementParameters() .stream() .forEach( a -> { System.out.println("elementId: " + a.getId()); } ); 

是否有任何解决方案使该流工作? 我使用eclipselink作为JPA提供者。

显然,你指的是这个问题 。 使用从实际实现(此处为Vector )inheritance的反模式的这些惰性列表无法适应基类的演变。 请注意,根据反模式的实现方式,有两种可能的结果

  • 如果在第一次使用时,延迟填充的列表会填充自身(它是inheritance状态的术语),新的inheritance方法将在第一次访问触发器属性时立即开始工作
  • 但是,如果列表覆盖所有访问器方法以强制委派给另一个实现,而不更新基类的状态,那么未被覆盖的基类的方法将永远不会开始工作,即使列表已被填充(来自子类的观点

显然,第二种情况适用于您。 触发列表的填充不会使inheritance的forEach方法起作用。 请注意,通过配置关闭延迟填充可能是更简单的解决方案。


对我来说,最干净的解决方案是,如果IndirectListinheritance自AbstractList并遵守Collection API标准,现在,在Collection API取代Vector后差不多二十年了(我应该提一下年轻的JPA实际上是多少?)。 不幸的是,开发人员没有走那条路。 相反,反模式通过创建另一个inheritance自已inheritance自未设计用于inheritance的类的类的类来最大化。 该类重写了Java 8中引入的方法,并且可能在下一个Java发行版中获得另一个子类。

所以好消息是,开发人员希望每个List都是Vector不必下定决心,但坏消息是它有时不起作用 ,你不会得到带有JPA 2.6的扩展Java 8特定版本。 但显然,JPA 2.7可行。

所以你可以得到一些替代解决方案:

  • 关掉懒惰的人口
  • 继续使用Java 7
  • 等待JPA 2.7
  • 只需复制集合,例如
    List workList=new ArrayList<>(elementParameters);
    workList将支持所有Collection&Stream操作