使用带有 DozerMaper 的 parallelStream 的对象映射列表给出 StackOverflowError
Mapping list of objects using parallelStream with DozerMaper gives StackOverflowError
我有以下实用方法将域对象列表映射到 DTO,从而生成映射对象列表。
public static <Z, T> List<T> mapList(Mapper mapper, List<Z> source, Class<T> type) {
List<T> result = new ArrayList<T>();
int listSize = source.size();
for (int i=0;i<listSize;i++) {
result.add(mapper.map(source.get(i), type));
}
return result;
}
作为映射器,我传递了 DozerBeanMaper 的单例实例(由 Spring 管理的实例)。列表源是休眠查询的结果。上面的代码工作得很好。
现在,我更改了代码以使用 Stream API(我想并行化映射):
public static <Z, T> List<T> mapList(Mapper mapper, List<Z> source, Class<T> type) {
return source.parallelStream()
.map((s) -> mapper.map(s, type))
.collect(Collectors.toList());
}
并得到以下内容:
Caused by: java.lang.NullPointerException
at org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:755)
at org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:75)
at org.hibernate.event.spi.InitializeCollectionEvent.<init>(InitializeCollectionEvent.java:36)
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1895)
at org.hibernate.collection.internal.AbstractPersistentCollection.doWork(AbstractPersistentCollection.java:558)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:766)
at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:850)
at org.dozer.MappingProcessor.mapListToList(MappingProcessor.java:686)
at org.dozer.MappingProcessor.mapCollection(MappingProcessor.java:553)
at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:434)
at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.mapCustomObject(MappingProcessor.java:495)
at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:446)
at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
at org.dozer.MappingProcessor.map(MappingProcessor.java:124)
at org.dozer.MappingProcessor.map(MappingProcessor.java:119)
at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120)
at
org.mycompany.myproject.utils.BeanMapperUtil.lambda[=12=](BeanMapperUtil.java:30)
重复执行并最终变成 WhosebugErrr。
如果我使用 source.stream()
而不是 source.parallelStream()
,我不会收到任何错误。
有什么想法吗?
问题在于该方法是在 spring @Transactional
注释方法中与延迟加载一起调用的。参见例如这个post]1
我有以下实用方法将域对象列表映射到 DTO,从而生成映射对象列表。
public static <Z, T> List<T> mapList(Mapper mapper, List<Z> source, Class<T> type) {
List<T> result = new ArrayList<T>();
int listSize = source.size();
for (int i=0;i<listSize;i++) {
result.add(mapper.map(source.get(i), type));
}
return result;
}
作为映射器,我传递了 DozerBeanMaper 的单例实例(由 Spring 管理的实例)。列表源是休眠查询的结果。上面的代码工作得很好。
现在,我更改了代码以使用 Stream API(我想并行化映射):
public static <Z, T> List<T> mapList(Mapper mapper, List<Z> source, Class<T> type) {
return source.parallelStream()
.map((s) -> mapper.map(s, type))
.collect(Collectors.toList());
}
并得到以下内容:
Caused by: java.lang.NullPointerException
at org.hibernate.engine.internal.StatefulPersistenceContext.getLoadedCollectionOwnerOrNull(StatefulPersistenceContext.java:755)
at org.hibernate.event.spi.AbstractCollectionEvent.getLoadedOwnerOrNull(AbstractCollectionEvent.java:75)
at org.hibernate.event.spi.InitializeCollectionEvent.<init>(InitializeCollectionEvent.java:36)
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1895)
at org.hibernate.collection.internal.AbstractPersistentCollection.doWork(AbstractPersistentCollection.java:558)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:766)
at org.dozer.MappingProcessor.addOrUpdateToList(MappingProcessor.java:850)
at org.dozer.MappingProcessor.mapListToList(MappingProcessor.java:686)
at org.dozer.MappingProcessor.mapCollection(MappingProcessor.java:553)
at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:434)
at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.mapCustomObject(MappingProcessor.java:495)
at org.dozer.MappingProcessor.mapOrRecurseObject(MappingProcessor.java:446)
at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:342)
at org.dozer.MappingProcessor.mapField(MappingProcessor.java:288)
at org.dozer.MappingProcessor.map(MappingProcessor.java:248)
at org.dozer.MappingProcessor.map(MappingProcessor.java:197)
at org.dozer.MappingProcessor.map(MappingProcessor.java:187)
at org.dozer.MappingProcessor.map(MappingProcessor.java:124)
at org.dozer.MappingProcessor.map(MappingProcessor.java:119)
at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120)
at
org.mycompany.myproject.utils.BeanMapperUtil.lambda[=12=](BeanMapperUtil.java:30)
重复执行并最终变成 WhosebugErrr。
如果我使用 source.stream()
而不是 source.parallelStream()
,我不会收到任何错误。
有什么想法吗?
问题在于该方法是在 spring @Transactional
注释方法中与延迟加载一起调用的。参见例如这个post]1