J'ai été chargé de refactoriser des composants qui utilisaient xmlbeans pour utiliser jaxb. Tout va bien, jusqu'à ce que j'arrive à un endroit où l'auteur précédent a appelé le copy() function of one of the XmlObjects. Puisque tous les objets dans xmlbeans étendent XmlObject, nous obtenons gratuitement la fonction de copie magique. Jaxb ne semble pas fournir cela pour nous. Quelle est la manière correcte et simple de faire une copie profonde d'un objet Jaxb?Comment faire une copie profonde de l'objet JAXB comme xmlbean XmlObject.copy()?
Répondre
Vous pouvez rendre vos classes JAXB sérialisables, puis copier en profondeur un objet en le sérialisant et en le désérialisant. Le code pourrait ressembler à:
Object obj = ... // object to copy
ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());
out.writeObject(obj);
byte[] bytes = baos.toByteArray();
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
Object copy = in.readObject();
Vous n'avez pas vraiment besoin de les rendre sérialisables, puisque l'objectif derrière JAXB est de rassembler des objets depuis et vers XML. Vous pouvez marshall et unmarhsall l'objet pour faire une copie, mais c'est probablement beaucoup moins efficace que d'écrire votre propre fonction clone(). – nsayer
+1 Je pense que c'est la bonne façon - il jives avec d'autres suggestions que j'ai vu. Merci pour le code d'exemple. –
Il est à noter qu'il y a une certaine surcharge [non-négligeable] (http://stackoverflow.com/a/10870833/521799) dans cette solution plutôt que d'utiliser 'Object.clone()' directement. Si la performance est importante, cela devrait être évité ... –
Vous pouvez déclarer une classe de base pour les objets JAXB générés à l'aide d'une annotation dans le XSD ...
<xsd:annotation>
<xsd:appinfo>
<jaxb:globalBindings>
<xjc:superClass name="com.foo.types.support.JaxbBase" />
</jaxb:globalBindings>
</xsd:appinfo>
</xsd:annotation>
Vous pouvez ajouter le support clonabilité il en utilisant la Classe de base xmlbeans en tant que modèle.
+1 J'aime vraiment cette idée - malheureusement, elle ne rentre pas dans notre cas d'utilisation (ce qui est un peu en dehors de la norme) –
Duh, une astuce si simple contourne tellement problèmes. Agréable! –
Vous pouvez utiliser JAXBSource
Dites que vous souhaitez copier en profondeur un SourceObject, de type Foo. Créer 2 JAXBContexts pour le même type:
JAXBContext sourceJAXBContext = JAXBContext.newInstance("Foo.class");
JAXBContext targetJAXBContext = JAXBContext.newInstance("Foo.class");
puis faites:
targetJAXBContext.createUnmarshaller().unmarshal(
new JAXBSource(sourceJAXBContext,sourceObject);
J'aime cette solution car elle utilise le framework JAXB, cependant le Context doit être créé non pas comme Foo.class mais avec l'espace de noms de schéma généré par JAXB. Vous devez le signaler sinon l'utilisateur obtiendra une erreur d'exception/d'exécution de la part de l'infrastructure qui ne parvient pas à trouver ObjectFactory. De plus, l'exemple aurait grandement avantage à ajouter le code réel pour obtenir l'objet (par exemple, Foo target = targetJAXBContext.createUnmarshaller ...) – count0
Vous pouvez consulter cette
public static <T> T deepCopyJAXB(T object, Class<T> clazz) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, object);
JAXBSource source = new JAXBSource(jaxbContext, contentObject);
return jaxbContext.createUnmarshaller().unmarshal(source, clazz).getValue();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
public static <T> T deepCopyJAXB(T object) {
if(object==null) throw new RuntimeException("Can't guess at class");
return deepCopyJAXB(object, (Class<T>) object.getClass());
}
Il fonctionne pour moi.
Tout le crédit va à https://gist.github.com/darrend/821410
Cela semble plus propre. – Espresso
- 1. Types de référence de copie profonde
- 2. Est-ce que Scala AnyRef.clone effectue une copie peu profonde ou profonde?
- 3. Objet de copie profonde LINQ to SQL avec dépendances
- 4. env.Clone() dans scons ne fait pas de copie profonde
- 5. Comment faire une copie d'un objet
- 6. Comment créer une collection profonde non modifiable?
- 7. JAXB: Types simples anonymes comme enums?
- 8. comment créer une sortie personnalisée de JAXB?
- 9. Comment vérifier si une valeur de matrice profonde est présente
- 10. Comment faire une copie en profondeur d'un élément dans LINQ to XML?
- 11. comment faire une navigation comme celle
- 12. Comment faire pour que Groovy et JAXB jouent bien ensemble
- 13. Faire une copie d'un type de béton inconnu en C++
- 14. Reliure profonde dans Flex
- 15. constructeur Copie: copie en profondeur une classe abstraite
- 16. Copie des informations ACL comme XCopy
- 17. Comment annuler une 'copie svn'
- 18. Liaison profonde XBAP. Menaces de sécurité possibles?
- 19. Liaison profonde dans JavaFX
- 20. Comment faire une copie exacte d'un graphe d'objet Données de base?
- 21. JAXB marshall structure complexe
- 22. Comment faire une implémentation OpenId comme dans stackoverflow
- 23. Comment faire une bordure inférieure comme dans finder?
- 24. Comment faire pour concevoir une interface comme celle-ci
- 25. Comment faire une copie d'un fichier de configuration existant en utilisant nant
- 26. Comment sérialiser une sous-classe Exception dans JAXB?
- 27. Comment ignorer une situation d'élément inattendue dans JAXB?
- 28. SVN: une copie de travail, deux dépôts?
- 29. JAXB Types problème
- 30. JAXB - problème étrange
Je suis curieux de savoir pourquoi vous vous déplacez de XMLBeans à JAXB, nous utilisons XMLBeans et avons envisagé la comparer à JIXB pour voir si nous pouvons obtenir des avantages de performance, Quelle était ta motivation pour le changement? – Tom
Eh bien, il y a quelques raisons, la raison principale étant que le support de xmlbeans enum est un peu sommaire, l'interface du code généré est un peu étrange et tous les objets étendent XmlObject et nous préférerions que les classes générées soient complètement indépendantes de tout pas inclus dans Java standard. Tout cela, et Jaxb n'est pas inclus dans la base jdk. –