2017-10-02 2 views
0

je me questionner sur la façon dont je pourrais réaliser ce scénario suivant:JPA persistent entité avec la stratégie de l'entité imbriquée rafraîchissante

Prenons une entité exemple Item

@Data 
@AllArgsConstructor 
@NoArgsConstructor(access = AccessLevel.PUBLIC) 
@Entity 
class Item implements Serializable { 
    @Id 
    @GeneratedValue 
    @Setter(AccessLevel.NONE) 
    private UUID id; 

    private String name; 

    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.REFRESH}) 
    @JoinTable(name = "item_category", joinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}, 
      inverseJoinColumns = {@JoinColumn(name = "category_id", referencedColumnName = "id")}) 
    private Set<Category> categories; 

    @PrePersist 
    protected void generateUuid() { 
     id = UUID_GENERATOR.generate(); 
    } 
} 

et Category

@Data 
@AllArgsConstructor 
@NoArgsConstructor(access = AccessLevel.PUBLIC) 
@Entity 
class Category implements Serializable { 
    @Id 
    @GeneratedValue 
    @Setter(AccessLevel.NONE) 
    private UUID id; 

    private String name; 

    @PrePersist 
    protected void generateUuid() { 
     id = UUID_GENERATOR.generate(); 
    } 
} 

Dans mon cas d'utilisation, Item devrait avoir beaucoup Category mais Item ne peut créer directement o r mettre à jour Category, il doit utiliser Category existant (image une liste déroulante des catégories gérées par l'administrateur). C'est pourquoi Cascade.PERSIST et Cascade.MERGE manquent.

Maintenant, imaginez la suite API POST /api/items avec une telle structure de demande JSON

{ 
    "name": "new item", 
    "categories": [ 
     "6d126e36-a7a5-11e7-abc4-cec278b6b50a", 
     "88d5a052-a7a5-11e7-abc4-cec278b6b50a" 
    ] 
} 

Cela devrait créer un nouveaux éléments existants avec Category avec données ids (considèrent que ids sont corrects et existent).

Cependant, je retourneraient réponse contenant des valeurs d'entités imbriquées Complets:

{ 
    "name": "new item", 
    "categories": [ 
     { 
      "id": "6d126e36-a7a5-11e7-abc4-cec278b6b50a", 
      "name": "CAT_A" 
     }, 
     { 
      "id": "88d5a052-a7a5-11e7-abc4-cec278b6b50a", 
      "name": "CAT_B" 
     } 
    ] 
} 

Pour éviter boilerplate, imaginez que Dto et DtoToEntityMapper (et arrière) sont présents et fonctionnent comme prévu.

Le problème est quand je persist() nouvelle entité Item produit de JSON:

Item(
    id=null, 
    name="new item", 
    Categories:[ 
    Category(
     id="6d126e36-a7a5-11e7-abc4-cec278b6b50a", 
     name=null 
    ), 
    Category(
     id="6d126e36-a7a5-11e7-abc4-cec278b6b50a", 
     name=null 
    ) 
    ] 
) 

Chaque ci-dessous par exemple sont détachés.

problème est après persist() tous les cas Category semble être détaché (ou au moins égal à name est encore null).

Alors, quelle est la meilleure façon de récupérer les champs Category?

  1. Dois-je utiliser refresh(item) après persist(item)?
  2. Dois-je utiliser attachéCategory au lieu de détaché et donc chaque Category à l'aide aller chercher id avant persist(item)?
  3. Puis-je utiliser le même représentation pour demande (POST corps de demande) et réponse, nommez ainsi sera pré-remplie. Mais que se passe-t-il si id est correct mais name ne l'est pas (puisque je n'accepte pas Category mise à jour de Item)? Ignorer simplement name ou déclencher une exception?
  4. Autre moyen

En outre, si 2. est la meilleure solution, où dois-je aller chercher ces entités imbriquées? Je veux dire dans Controller (couche de présentation), dans DtoToEntityMapper (couche de présentation), dans Service (couche de service)


PS: S'il vous plaît, je collerait à JPA spécifications et ne pas utiliser Hibernate caractéristiques spécifiques . PS2: Je serais en mesure de le faire en simple POST demande

Répondre

1

En utilisant entityManager.merge() au lieu de entityManager.persist() devrait faire l'affaire. Il renverra l'instance gérée afin d'accéder à ses catégories devrait vous donner les catégories, y compris la description.

Remarque: Veillez à utiliser l'instance gérée après l'appel.