jaxb - отношения многие ко многим

1

РЕДАКТИРОВАТЬ:

Я перепутал некоторое время и пришел к следующему результату XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<List>
    <client name="Robert">
        <fileNames name="anleitung.pdf"/>
        <fileNames name="fernseher.jpg"/>
        <fileNames name="pikantesfoto.jpg"/>
    </client>
    <client name="Jakob">
        <fileNames name="fernseher.jpg"/>
        <fileNames name="pikantesfoto.jpg"/>
        <fileNames name="tagebuch.txt"/>
    </client>
</List>

Это не очень много отношений, но это близко, мне нужно удалить избыточность данных.

"Имена файлов" должны быть отдельными элементами, которые и клиенты должны указывать на них. Поэтому, если есть один файл с тем же именем файла с других клиентов, он должен появляться только один раз.

Это мои классы:

Маршаллер: открытый класс XMLMarshaller {

private Pool pool;

public XMLMarshaller(Pool pool) {
    this.pool = pool;
}

public void marshal() {

    JAXBContext jc;
    try {
        jc = JAXBContext.newInstance(Pool.class, Client.class, FileName.class);

        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Save XML-File");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("XML-Document", "*.xml"));

        File path = fileChooser.showSaveDialog(new Stage());
        if (path.toString().endsWith(".xml") == false) {
            path = new File(path.toString() + ".xml");
        }
        if (path.isFile() == false)
            path.createNewFile();

        FileOutputStream fos = new FileOutputStream(path);
        OutputStreamWriter xmlOut = new OutputStreamWriter(fos, Charset.forName("UTF8"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        QName qName = new QName("List");
        JAXBElement<Pool> jaxbElement = new JAXBElement<>(qName, Pool.class, pool);
        marshaller.marshal(jaxbElement, xmlOut);

        xmlOut.flush();
        xmlOut.close();
    } catch (Exception e) {e.printStackTrace();}
}

}

Пул (содержит список всех существующих "имен файлов" и "Клиенты"):

public class Pool {

private List<FileName> fileNames_pool;
private List<Client> clients;

public Pool() {
    this.fileNames_pool = new ArrayList<>(20);
    this.clients = new ArrayList<>(20);
}

public List<FileName> getFileNameList() {
    return this.fileNames_pool;
}

public List<FileName> getFileNames_pool() {
    return this.fileNames_pool;
}

@XmlAnyElement(lax = true)
public List<Client> getClientList() {
    return this.clients;
}


public boolean addClient(String clientName) {
    this.clients.add(new Client(clientName));
    return true;
}

public boolean addFileName(int clientIndex, String fileName) {

    int foundIndex = 0;
    boolean foundOne = false;

    for (int i=0; i<fileNames_pool.size(); ++i) {
        if (fileNames_pool.get(i).name == fileName) {
            foundIndex = i;
            foundOne = true;
            break;
        }
    }

    if (foundOne) {
        clients.get(clientIndex).addFileName(fileNames_pool.get(foundIndex));
    } else {
        FileName temp = new FileName(fileName);
        fileNames_pool.add(temp);
        clients.get(clientIndex).addFileName(temp);
    }
    return true;
}

}

Клиент (там будет несколько экземпляров/объектов): @XmlRootElement public class Client {

static int numberOfClients = 0;

private int id;

@XmlAttribute
public String name;

public List<FileName> fileNames = new ArrayList<>();

public Client() {

}

public Client(String name) {
    this.name = name;
    this.id = numberOfClients++;
}

@XmlElement
public List<FileName> getFileNames() {
    return this.fileNames;
}

public void addFileName(FileName fileName) {
    this.fileNames.add(fileName);
}

}

FileNames (там также будут несколько экземпляров):

//@XmlRootElement
public class FileName {

//  public static int instanceCounter = 0;
//  
//  @XmlIDREF
//  public int idref = 0;

    @XmlAttribute
    public String name;

    public FileName() {

    }

    public FileName(String name) {
        this.name = name;
//      idref = instanceCounter++;
    }
}

Вы увидите, что я иногда действительно перепутал вещи, но у меня совершенно нет идей о том, что может сработать, а что нет. Класс пула - это что-то вроде обертки, как сказал мне Блейз Дохан, если я не ошибаюсь. И что я полностью не понял: почему должен быть "id", основанный на классе строк?

Теги:
many-to-many
jaxb

2 ответа

1

Требования JAXB

Каждый объект должен быть ссылкой через отношения сдерживания/вложения, такие как @XmlElement, @XmlElementRef или @XmlAnyElement(lax=true).

Неконтаминационные отношения

Если у вас есть дерево, как формируется выше требования JAXB вы можете формировать отношения внутри документа с использованием @XmlID/@XmlIDREF (см http://blog.bdoughan.com/2010/10/jaxb-and-shared-references- xmlid-and.html). Вот где следующее выражение, сделанное вами в вашем вопросе, происходит от:

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

Что ты можешь сделать?

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

  • 0
    Привет Блейз :) Я сейчас нахожусь на этом, чтобы получить то, что вы имеете в виду (с ~ 1 часа). Мой английский, к сожалению, не самый лучший. Я знаю, что это очень мало по сравнению со стандартом UML, но ты имеешь в виду что-то подобное? bilder-hochladen.net/files/big/1fby-6q-0116.png Завтра (я надеюсь) я посмотрю ближе к вашей второй ссылке. Кажется, мне также нужно немного больше погрузиться в мир «баз данных». Большое спасибо за вашу работу здесь! :)
  • 0
    Я полностью отредактировал свой главный вопрос и был бы очень рад, если бы вы посмотрели на него, Блейз. XML будет работать, но я так и не достиг результата, который искал. Привет, Трудлер
1

Вот пример того, как сопоставить POJO с XML с помощью jaxb http://www.mkyong.com/java/jaxb-hello-world-example/

Однако в вашем случае у вас двунаправленные отношения, ваш класс ClientName имеет ссылку на класс FileName, а в FileName возвращается ссылка на ClientName. В случае двунаправленного XML-сопоставления с использованием JAXB вы захотите использовать тег @XmlTransient для одного из отношений. @XmlTransient может не быть тем, что вы ищете, потому что для любого поля аннотируется, оно будет удалено с этого направления. Существует решение этого с использованием метода afterUnmarshal. http://www.tutorialspoint.com/java/xml/javax_xml_bind_unmarshaller.listener_afterunmarshal.htm

Или вы можете использовать MOXy @XmlInverseReference для обработки unmarshalling для вас https://www.eclipse.org/eclipselink/documentation/2.4/moxy/shared_reference_relationships005.htm

Ещё вопросы

Сообщество Overcoder
Наверх
Меню