Так что у меня возникла проблема, что кто-то здесь может помочь мне с Dozer.Dozer Not Mapping Collection Правильно
Фон: У меня есть дозатор, настроенный для сопоставления объектов сущности с их классами DTO. Это довольно просто, я просто создаю точную копию моего класса сущности как POJO и разрешаю дизерам-димерам, чтобы увидеть, что имя поля соответствует полю источников. Я обрабатываю спящий режим ленивой загрузки с помощью настраиваемого картографа, как сделано here. Я рассказываю Dozer о том, как сопоставить каждый класс с помощью класса, который сканирует аннотацию, называемую @EntityMapping (DTOxxx.class) внутри объекта. Затем он добавляет его к картографа addMapping (строитель)
Вопрос: (Прочитайте исследования в конце концов, для актуальной информации, но это поможет получить контекст, прочитав все это тоже) проблема заключается в том, что Dozer не правильно отображает мои коллекции в некоторых случаях. Например, в моем классе CategoryEntity у меня есть коллекция других объектов, которые необходимо отобразить Dozer. Что происходит, так это то, что бульдозер находит коллекцию, которая имеет в этом случае 2 элемента и отображает только 1 элемент в новой коллекции классов DTO.
Как вы можете видеть на изображении после toDomain называется (это имеет mapper.map (источник, Desination) бульдозер вызова в нем) и DTO имеет только 1 из 2-х объектов, которые он должен иметь отображаемый в нем из объекта. Вот метод toDomain опалубить вы хотите увидеть:
@Transactional(readOnly=true)
public <T extends DomainObject> T toDomain(Class<T> clazz, Entity entity) {
if (entity == null) {
return null;
}
T domain = getCachedDomainObjects(clazz, entity.getId());
if (domain == null) {
domain = dozerMapper.map(entity, clazz);
cacheDomainObject(domain);
}
return domain;
}
Я сделал уверен, что его не захватывая кэшированный объект, если вы думаете, что.
Так что я немного зациклен на то, почему это происходит в некоторых случаях, а не в других случаях. Я не вижу никаких очевидных различий в тех случаях, когда он работает, и случаев, когда он не работает. Если кто-то столкнулся с такой проблемой раньше и подумает, что они смогут мне помочь, это было бы фантастически! Вот мои классы на примере выпуска:
CategoryEntity.java:
@EntityMapping(Category.class)
@javax.persistence.Entity(name = "categories")
public class CategoryEntity implements Entity, PureTable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private int id = Entity.UNSAVED_ID;
@OneToMany(mappedBy = "pk.category", fetch = FetchType.LAZY)
@Cascade({CascadeType.SAVE_UPDATE})
private Set<IncidentJoinCategoryEntity> incidentJoinCategories =
new HashSet<IncidentJoinCategoryEntity>();
@Override
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public Set<IncidentJoinCategoryEntity> getIncidentJoinCategories() {
return incidentJoinCategories;
}
public void setIncidentJoinCategories(Set<IncidentJoinCategoryEntity>
incidentJoinCategories) {
this.incidentJoinCategories = incidentJoinCategories;
}
}
Этот класс имеет класс DTO, который соответствует его ценности полностью:
Category.java:
public class Category {
int id;
Set<IncidentJoinCategory> incidentJoinCategories=
new HashSet<IncidentJoinCategory>();
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
public Set<IncidentJoinCategory> getIncidentJoinCategories() {
return incidentJoinCategories;
}
public void setIncidentJoinCategories(Set<IncidentJoinCategory>
incidentJoinCategories) {
this.incidentJoinCategories = incidentJoinCategories;
}
}
!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!! ИССЛЕДОВАНИЕ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EDIT # 1:
Хорошо! Поэтому я потратил несколько часов на отладку этой проблемы, чтобы узнать, что здесь происходит. Оказывается, проблема связана с классом класса MappingProcessor 749 (Dozer 5.4.0) или с линией 766 для последних источников (но я не проверял, все еще проблема в последних источниках, сомневаюсь, что она исправлена).
Эта линия
((Set) field).addAll(result);
Что он пытается отобразить здесь является
HashSet<IncidentJoinCategoryEntity>
addAll (результат) только при добавлении 1 пункт к ((Set) поле) коллекции. Результат, в котором есть 2 элемента (во время отладки это также размер 2, я предоставил свой снимок переменных) добавляет только 1 значение в поле ((Установить)).
result LinkedHashSet<E> (id=220)
map LinkedHashMap<K,V> (id=248)
accessOrder false
entrySet HashMap$EntrySet (id=251)
hashSeed -1187793029
header LinkedHashMap$Entry<K,V> (id=253)
keySet HashMap$KeySet (id=5829)
loadFactor 0.75
modCount 2
size 2
table HashMap$Entry<K,V>[16] (id=258)
threshold 12
useAltHashing false
values null
field HashSet<E> (id=221)
map HashMap<K,V> (id=247)
entrySet HashMap$EntrySet (id=5856)
hashSeed 1372273954
keySet HashMap$KeySet (id=5821)
loadFactor 0.75
modCount 2
size 1
table HashMap$Entry<K,V>[16] (id=5822)
threshold 12
useAltHashing false
values null
EDIT # 2:
Загрузили источник для дополнительной отладки:
if (field == null) {
Class<? extends Set<?>> destSetType = (Class<? extends Set<?>>) fieldMap.getDestFieldType(destObj.getClass());
return CollectionUtils.createNewSet(destSetType, result);
} else {
System.out.println("----IN----");
// Bug #1822421 - Clear first so we don't end up with the removed orphans again
Set ret = (Set) field;
ret.clear();
//((Set) field).addAll(result);
for(Object res : result) {
System.out.println("FOUND " + res.toString());
ret.add(res);
}
System.out.println("END SIZE " + ret.size());
System.out.println("----OUT----");
return ret;
}
выход для этого случая:
----IN----
FOUND nz.c[email protected]3e2
FOUND nz.c[email protected]3e2
END SIZE 1
----OUT----
Его выход - 2 элемента, но, как вы можете видеть @ 3e2, они по каким-то причинам одни и те же. Поэтому, когда вы вызываете addAll, он удаляет дубликат и оставляет нас всего за 1 элемент. Почему Dozer случайно отображает 2 одинаковых значения? Я проверил, чтобы в коллекции исходных объектов не было одинаковых элементов, и, конечно же, это не так. Странно.
EDIT # 3:
Я сделал дальнейшие тесты с небольшим количеством удачи здесь. Это действительно проблема с отображением Dozer 2 одинаковых значений, а addAll выбивает дубликат, делая его только одним элементом в списке. К сожалению, я не могу отлаживать рекурсивные методы в addToSet очень легко, чтобы определить, почему это происходит.
Будет обновлено, если я что-нибудь придумаю, иначе у меня есть идеи об этом ха-ха.