2013-06-27 5 views
0

Так что у меня возникла проблема, что кто-то здесь может помочь мне с Dozer.Dozer Not Mapping Collection Правильно

Фон: У меня есть дозатор, настроенный для сопоставления объектов сущности с их классами DTO. Это довольно просто, я просто создаю точную копию моего класса сущности как POJO и разрешаю дизерам-димерам, чтобы увидеть, что имя поля соответствует полю источников. Я обрабатываю спящий режим ленивой загрузки с помощью настраиваемого картографа, как сделано here. Я рассказываю Dozer о том, как сопоставить каждый класс с помощью класса, который сканирует аннотацию, называемую @EntityMapping (DTOxxx.class) внутри объекта. Затем он добавляет его к картографа addMapping (строитель)

Вопрос: (Прочитайте исследования в конце концов, для актуальной информации, но это поможет получить контекст, прочитав все это тоже) проблема заключается в том, что Dozer не правильно отображает мои коллекции в некоторых случаях. Например, в моем классе CategoryEntity у меня есть коллекция других объектов, которые необходимо отобразить Dozer. Что происходит, так это то, что бульдозер находит коллекцию, которая имеет в этом случае 2 элемента и отображает только 1 элемент в новой коллекции классов DTO.

enter image description here

Как вы можете видеть на изображении после 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  

enter image description here

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 очень легко, чтобы определить, почему это происходит.

Будет обновлено, если я что-нибудь придумаю, иначе у меня есть идеи об этом ха-ха.

ответ

0

Оказывается, это на самом деле не ошибка бульдозера. Отладка предположила, что Dozer был виновником, но я не думаю, что это так. Причина. Я думаю, это связано с тем, что я перешел к другому картографу с той же проблемой, поэтому, если у этого нового картографа не будет той же проблемы (LOL), это не Dozer. Если кто-нибудь знает, почему это происходит для меня, я был бы признателен за помощь в этом.

Моей догадкой в ​​данный момент является настраиваемое полевое устройство спящего режима, которое у меня есть, чтобы иметь дело с ленивыми коллекциями, чувствительными к нагрузке. Единственная причина, по которой я проигнорировал это, в первую очередь состоит в том, что, когда я начал отлаживать Dozer, казалось, что Dozer сопоставлял поля, прежде чем он возвращался из addToSet, поэтому я ошибочно предположил, что он уже применил настраиваемое сопоставление полей.

 Смежные вопросы

  • Нет связанных вопросов^_^