2009-10-07 5 views
4

Мы используем Джерси (библиотека Java REST) ​​для проекта в течение последних нескольких месяцев и любим его. Но эта неделя столкнулась с проблемой с JAXB.JAXB и множественные отношения объектов

У меня есть элемент, который имеет 2 детей, у каждого из них есть дети, где некоторые из их детей ссылаются друг на друга.

Позвольте мне показать код.

Root root = new Root(); 

Parent parent1 = new Parent(); 
Parent parent2 = new Parent(); 

root.add(parent1); 
root.add(parent2); 

Child child1 = new Child(); 
Child child2 = new Child(); 
Child child3 = new Child(); 

parent1.add(child1); 
parent1.add(child2); 

parent2.add(child2); 
parent2.add(child3); 

Итак, у нас есть 1 корень, 2 родителя и 3 ребенка.

Если я отправлю это вверх и вниз по пути JAXB, я, кажется, вернусь к 4 детям.
У каждого родителя есть своя копия child2.

Есть ли все-таки, чтобы заставить JAXB сериализовать отношения и показать, что оба родителя1 и родительский 2 указывают на один и тот же объект?

Мы недавно обнаружили эту проблему, когда передавались более сложные элементы.

Если у вас нет способа заставить JAXB сделать это (это то, во что я верю в данный момент), есть ли у кого-нибудь какие-либо предложения о том, как я мог бы сделать магию в Джерси, чтобы восстановить отношения?

ответ

3

Это не проблема с JAXB, так как это проблема с вашей моделью. Как вы хотите, чтобы JAXB отображал ваши отношения в XML, когда XML не предоставляет стандартного механизма для выражения этого? И потребителю, и производителю XML необходимо будет иметь уровень бизнес-логики, который бы согласился на повторное представление.

Предлагаю вам переделать данные. Например, вместо того, чтобы иметь ребенок, как, которая содержится внутри родителей, вы могли бы сгладить вещи:

<parent id="parent1"> 
    <child ref="child1"/> 
    <child ref="child2"/> 
</parent> 

<parent id="parent2"> 
    <child ref="child2"/> 
    <child ref="child3"/> 
</parent> 

<child id="child1"/> 
<child id="child2"/> 
<child id="child3"/> 

Каких бы механизм чтение и записи этой структуры будет знать, что все это значит, но я не вижу любой другой хороший способ сделать это.

Другой интересный объект состоит в том, что XStream имеет support for object references, когда он сериализует/десериализует графы объектов, но это полностью проприетарный механизм.

0

Просто подумайте: сделайте необходимые объекты Childequals()?

1

вы могли бы это сделать, написав класс адаптера для класса Root, который при unmarshalling может очистить дочерние объекты, чтобы удалить дубликаты.

0

Как уже было сказано в других ответах. Это дизайн JAXB.

Что вы можете сделать, это вручную приклеить несколько копий того, что, по вашему мнению, было одним и тем же объектом перед сериализацией. Тогда вам не понадобится ваш собственный идентификатор для объектов, чтобы вы могли разглядеть отдельные клоны только от других объектов.

8

JAXB поддерживает ссылки без ограничений между объектами в дереве, используя комбинацию @ XmlID/@ XmlIDREF. Требование для этого состоит в том, что на все объекты в дереве также должны ссылаться отношения сдерживания. В вашей модели это может включать в себя предоставление Root коллекции Child.

Ниже будет модифицированная версия кода:

Root root = new Root(); 

Parent parent1 = new Parent(); 
Parent parent2 = new Parent(); 

root.add(parent1); 
root.add(parent2); 

Child child1 = new Child(); 
child1.id = "1"; 
root.add(child1); 
parent1.add(child1); 

Child child2 = new Child(); 
child2.id = "2"; 
root.add(child2); 
parent1.add(child2); 
parent2.add(child2); 

Child child3 = new Child(); 
child3.id = "3"; 
root.add(child3); 
parent2.add(child3); 

Тогда модельные классы будут выглядеть следующим образом:

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Root { 

    public List<Parent> parent = new ArrayList<Parent>(); 
    public List<Child> child = new ArrayList<Child>(); 

    public void add(Parent parent1) { 
     parent.add(parent1); 
    } 

    public void add(Child child1) { 
     child.add(child1); 
    } 
} 

import javax.xml.bind.annotation.XmlIDREF; 

public class Parent { 

    @XmlIDREF 
    public List<Child> child = new ArrayList<Child>(); 

    public void add(Child child1) { 
     child.add(child1); 
    } 

} 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlID; 

public class Child { 

    @XmlID 
    @XmlAttribute 
    public String id; 

} 

В результате XML будет выглядеть следующим образом:

<root> 
    <parent> 
     <child>1</child> 
     <child>2</child> 
    </parent> 
    <parent> 
     <child>2</child> 
     <child>3</child> 
    </parent> 
    <child id="1"/> 
    <child id="2"/> 
    <child id="3"/> 
</root> 

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

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