Nous avons cette configuration : Un document possède une liste d'éléments et ces éléments sont des sous-classes d'Element, dans cet exemple Link. Un lien a une relation @OneToOne avec une ressource. Tout a fonctionné tant que nous avons créé l'ensemble du graphe d'objets en une seule étape.
Nous avons maintenant modifié notre code pour créer une instance de Resource, la faire persister et la transmettre à notre client (web, objets sérialisés en JSON). Le client crée une instance du document et ajoute un lien avec la ressource existante. Ensuite, nous essayons de persister le nouveau document.
À ce stade, l'opération échoue, car JPA tente de conserver la ressource existante avec le même identifiant. Je pense que cela se produit parce que la ressource est détachée et que JPA n'a aucun moyen de déterminer si cette entité doit être fusionnée ou persistée. Lorsque je supprime le CascadeType.ALL et que je le remplace par CascadeType.MERGE, tout se passe bien, sauf que la ressource n'est pas du tout mise à jour.
En principe, le processus est le suivant :
- créer et conserver une ressource
- opération de congé
- démarrer la transaction
- créer un document avec un lien et une ressource (détachée)
- erreur
Y a-t-il un problème avec notre configuration JPA (voir nos entités) ? Je serais ravi de vous offrir une bière si vous pouviez me donner un indice... :-) TYIA.
Notre configuration est la suivante : EclipseLink 2.4.1, Spring Data JPA 1.3.0 (utilisant @Repository) avec PostgreSQL 9.2.
Document :
@Entity
public class Document implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@OrderColumn
@JoinColumn(name = "document_id")
private List<Element> elements = new ArrayList<Element>();
// getters and setters
}
Élément :
@Entity
@Inheritance(strategy = InheritanceType.
public class Element implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "document_id", insertable = false, updatable = false)
private Document document;
// getters and setters
}
Lien :
@Entity
public class Link extends Element {
@Column
private String appearance;
@Column
private String referenceType;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Resource resource;
// getters and setters
}
Ressource :
@Entity
public class Resource {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column
private String uri;
// getters and setters
}