代码之家  ›  专栏  ›  技术社区  ›  draganstankovic

如何使用Hibernate和Web服务保持具有两个父级的实体?

  •  1
  • draganstankovic  · 技术社区  · 15 年前

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

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

    我希望将实体A与Hibernate一起持久化,但我正在通过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。

    1 回复  |  直到 15 年前
        1
  •  1
  •   bdoughan    15 年前

    两种方法都是合理的:

    两次调用Web序列

    一些用户正在将消息分成更小的块,以便在单个消息中只有私有数据通过导线发送。对非私有数据的引用表示为链接(链接指定如何从另一个JAX-RS服务获取对象)。然后,您可以让XML适配器解析链接(请参见下面的内容):

    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是合适的。下面是我和一个用户关于自动化这个的一个线程:

    循环引用

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