如何使用 hibernate 和 web 服务持久保存具有两个父级的实体?

发布于 2024-09-11 11:30:54 字数 715 浏览 3 评论 0原文

我有以下实体结构(A、B、C、D 是实体):

A-> one-to-many B, 
A-> one-to-many C,
B-> one-to-many D, 
C-> one-to-many D.

我想用 hibernate 持久保存实体 A,但我通过 Web 服务发送它(消除了循环引用)。因此,在服务器上,我收到“了解”孩子的父母,而孩子不了解父母,我需要再次将所有内容链接起来。问题是我需要将 D 与两个父级相匹配 - 客户端上的单个 D 实例在服务器上变成了必须合并的两个实例,并且 D 之前没有被持久化,因此它不包含唯一的 id可以匹配的。我正在考虑两个解决方案:

1.  Call web service twice – in first call persist Ds and then call it to persist A
2.  XmlIDRef, and XmlID annotations so I don’t have to merge Ds (jaxb will do the job for me) but in that case client will have to generate unique ids for that fields and I wanted to avoid that.

我该怎么做?我走在正确的轨道上吗?

顺便说一句,我正在使用 hibernate、cxf 和 jaxb。

I have the following entity structure (A, B, C, D are entities):

A-> one-to-many B, 
A-> one-to-many C,
B-> one-to-many D, 
C-> one-to-many D.

I want to persist entity A with hibernate but I am sending it over web service (cyclic references are eliminated). So, on the server I receive parents that “know” about the children and children don’t know about the parents and I need to link everything up again. The problem is that I need to match D with two parents - what was on the client a single D instance, on the server became two instances which have to be merged and D hadn’t been previously persisted so it doesn’t contain unique id that can be matched. I am thinking about two solutions:

1.  Call web service twice – in first call persist Ds and then call it to persist A
2.  XmlIDRef, and XmlID annotations so I don’t have to merge Ds (jaxb will do the job for me) but in that case client will have to generate unique ids for that fields and I wanted to avoid that.

How should I do it? Am I on the right track?

Btw, I am using hibernate, cxf and jaxb.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼趣 2024-09-18 11:30:54

两种方法都是合理的:

调用 Web 服务两次

一些用户将消息分成更小的块,以便在单个消息中仅通过线路发送私有数据。对非私有数据的引用表示为链接(链接指定如何从另一个 JAX-RS 服务获取对象)。然后,您可以使用 XmlAdapter 来解析链接(见下文):

import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.adapters.XmlAdapter;

import org.example.product.Product;

public class ProductAdapter  extends XmlAdapter<String, Product>{

    private JAXBContext jaxbContext;

    public ProductAdapter() {
        try {
            jaxbContext = JAXBContext.newInstance(Product.class);
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String marshal(Product v) throws Exception {
        if(null == v) {
            return null;
        }
        return "http://localhost:9999/products/" + v.getId();
    }

    @Override
    public Product unmarshal(String v) throws Exception {
        if(null == v) {
            return null;
        }

        URL url = new URL(v);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", "application/xml");

        Product product = (Product) jaxbContext.createUnmarshaller().unmarshal(connection.getInputStream());
        connection.disconnect();
        return product;
    }

}

@XmlID/@XMLIDREF

如果您打算在一次调用中发送所有数据,并且 B 和 C 共享对 D 实例的引用,那么您将需要@XmlID/@XmlIDREF。您将需要一个对象来嵌套 D 的实例。在这种情况下,A 下是合适的。下面是我与用户讨论的关于自动化此操作的线程:

循环引用

MOXy JAXB 实现具有用于处理循环的扩展关系。这是通过 @XmlInverseReference 注释完成的。有关详细信息,请参阅:

Both approaches are reasonable:

Call Web Serice Twice

Some users are breaking the messages into smaller chunks so that only privately owned data is sent over the wire in a single message. References to non-privately owned data is represented as links (the links specify how to get the object from another JAX-RS service). Then you can have XmlAdapters that resolve the links (see below):

import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.adapters.XmlAdapter;

import org.example.product.Product;

public class ProductAdapter  extends XmlAdapter<String, Product>{

    private JAXBContext jaxbContext;

    public ProductAdapter() {
        try {
            jaxbContext = JAXBContext.newInstance(Product.class);
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String marshal(Product v) throws Exception {
        if(null == v) {
            return null;
        }
        return "http://localhost:9999/products/" + v.getId();
    }

    @Override
    public Product unmarshal(String v) throws Exception {
        if(null == v) {
            return null;
        }

        URL url = new URL(v);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", "application/xml");

        Product product = (Product) jaxbContext.createUnmarshaller().unmarshal(connection.getInputStream());
        connection.disconnect();
        return product;
    }

}

@XmlID/@XMLIDREF

If you are going to send all the data in one call and B and C share references to instances of D, then you will need @XmlID/@XmlIDREF. You will need an object to nest the instances of D under. In this case under A would be appropriate. Below is a thread I had with a user about automating this:

Cyclic References

The MOXy JAXB implementation has extensions for handling cyclic relationships. This is done through the @XmlInverseReference annotation. For more information see:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文