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.
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:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.