java - jaxb-多对多关系

标签 java jaxb many-to-many

编辑:

我闲逛了一段时间,得到了以下 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>

这并不是真正的多对多关系,但它很接近,我需要删除数据冗余。

“文件名”应该是单个元素,客户端应该指向它。因此,如果有一个文件与其他客户端的文件同名,则该文件应该只出现一次。

这是我的类(class):

编码员: 公共(public)类 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)类客户端{

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);
}

}

文件名(也会有多个实例):

//@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++;
    }
}

你会发现我有时真的把事情搞砸了,但我完全不知道什么可行,什么不可行。如果我没有理解错的话,Pool 类就像 Blaise Doughan 告诉我的那样,是一个 Wrapper。我完全不明白的是:为什么应该有一个基于字符串类的“id”?

最佳答案

下面是如何使用 jaxb http://www.mkyong.com/java/jaxb-hello-world-example/ 将 POJO 映射到 XML 的示例

但是,在您的情况下,您具有双向关系,您的 ClientName 类具有对 FileName 类的引用,并且 FileName 具有引用回 ClientName。对于使用 JAXB 的双向 XML 映射,您将需要在其中一个关系上使用 @XmlTransient 标记。 @XmlTransient 可能不是您要查找的内容,因为无论注释哪个字段,它都会从该方向删除。有一个解决方案,使用 afterUnmarshal 方法。 http://www.tutorialspoint.com/java/xml/javax_xml_bind_unmarshaller.listener_afterunmarshal.htm

或者您可以使用 MOXy 的 @XmlInverseReference 来为您处理解码 https://www.eclipse.org/eclipselink/documentation/2.4/moxy/shared_reference_relationships005.htm

关于java - jaxb-多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22513256/

相关文章:

java - 如何在Hibernate中对关联映射表执行软删除?

java - 如何解决无法获取隔离的 JDBC 连接的问题?

java - JTextArea 中的文本更改事件?如何?

java - 尝试使用 jersey 和 jaxb 时出现异常

java - 使用 JAXB 解码

sql - 使用 SQL 和 Linq 的多对多关系( Entity Framework /实体)

java - 使用 JavaRdd<Row> 映射 Spark DataFrame 列值

java - 使用 GremlinPipeline 查找最短路径

Java:XML 到对象以及对象到带有属性的 XML

sql - Grails 多对多 sql