JPA惰性列表上的流
我的 JPA 实体列表如下:
I have JPA entity with list like this:
@OneToMany(mappedBy = "scadaElement", orphanRemoval = true)
private List<ElementParameter> elementParameters;
和map形式的ElementParameter
and map form ElementParameter
@ManyToOne
@JoinColumn(name = "SCADAELEMENT_ID")
ScadaElement scadaElement;
当我使用 elementParameters 列表获取实体并在其上执行流时,流什么也不做,即使我使用 .size() 触发列表但当我使用 for 循环执行相同操作时它也可以工作.
when i get entity with elementParameters list and do stream on it stream do nothing, even when I trigger list with .size() but when I do the same with a for loop it work.
System.out.println("elements size: " + s.getElementParameters().size());
s.getElementParameters()
.stream()
.forEach(
a -> {
System.out.println("elementId: " + a.getId());
}
);
是否有任何解决方案可以使该流工作?我使用 eclipselink 作为 JPA 提供者.
Is there any solution to make that stream work? I use eclipselink as JPA provider.
推荐答案
显然,你指的是这个问题.这些使用从实际实现(此处为 Vector
)继承的反模式的惰性列表无法适应基类的演变.请注意,根据反模式的实现方式,有两种可能的结果
Apparently, you are referring to this issue. These lazy lists using the anti-pattern of inheriting from actual implementations (here Vector
) fail to adapt to the evolution of the base class. Note that there are two possible outcomes depending on how the anti-pattern was realized
- 如果延迟填充的列表在第一次使用时自行填充(它是继承状态的术语),则新继承的方法将在第一次访问触发器属性后立即开始工作
- 但是,如果列表覆盖所有访问器方法以强制委托给另一个实现,而无需更新基类的状态,则即使列表已被填充,未被覆盖的基类方法也将永远不会开始工作(从子类的角度来看)
显然,第二种情况适用于您.触发列表的填充不会使继承的 forEach
方法起作用.请注意,通过配置关闭惰性人口可能是这里更简单的解决方案.
Apparently, the second case applies to you. Triggering the population of the list does not make the inherited forEach
method work. Note that turning off the lazy population via configuration might be the simpler solution here.
对我来说,最干净的解决方案是,如果 IndirectList
继承自 AbstractList
并遵守 Collection API 标准,现在,距离 Collection API 已经取代 Vector
(我应该提一下 JPA 实际上年轻了多少?).不幸的是,开发商没有走那条路.相反,反模式通过创建另一个类来最大化,该类继承自已经继承自非为继承而设计的类的类.此类会覆盖 Java 8 中引入的方法,并且可能会在下一个 Java 版本中获得另一个子类.
To me, the cleanest solution would be if IndirectList
inherits from AbstractList
and adheres to the Collection API standard, now, almost twenty years after the Collection API has superseded Vector
(should I mention how much younger JPA actually is?). Unfortunately, the developers didn’t go that road. Instead, the anti-pattern was maxed out by creating another class that inherits from the class which already inherits from the class not designed for inheritance. This class overrides the methods introduced in Java 8 and perhaps gets another subclass in one of the next Java releases.
所以好消息是,希望每个 List
都是 Vector
的开发人员不必下定决心,但坏消息是 它不起作用 因为有时,您不会获得扩展的 Java 8 特定版本使用 JPA 2.6.但显然,JPA 2.7 可以工作.
So the good news is, developers expecting every List
to be a Vector
do not have to make up their minds, but the bad news is it doesn’t work as sometimes, you will not get the extended Java 8 specific version with JPA 2.6. But apparently, JPA 2.7 will work.
因此您可以推导出一些替代解决方案:
So you can derive a few alternative solutions:
- 关闭惰性人口
- 继续使用 Java 7
- 等待 JPA 2.7
- 只需复制集合,例如
列表<元素参数>workList=new ArrayList
(elementParameters);
这个workList
将支持所有 Collection &流操作
- Turn off lazy population
- Stay with Java 7
- Wait for JPA 2.7
- just copy the collection, e.g.
List<ElementParameter> workList=new ArrayList<>(elementParameters);
ThisworkList
will support all Collection & Stream operations
相关文章