[JAVA] [JPA] Comment enregistrer lorsque vous avez des éléments autres que des clés dans la table d'intersection liés à ManyToMany

introduction

Le mappage avec la table d'intersection est toujours ennuyeux. Cette fois, je présenterai la méthode d'enregistrement lorsque vous avez une clé non composite dans la table d'intersection.

Enregistrement de la clé composée uniquement

Tout d'abord, supposons que vous ayez une entité avec les relations suivantes:

1.png

La méthode de sauvegarde dans ce cas est la suivante.

Maître des utilisateurs


@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
@Entity
@Table
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String status;

    @ManyToMany
    @JoinTable(name = "user_service",joinColumns = @JoinColumn(name="user_id"), referencedColumnName="id"
              inverseJoinColumns = @JoinColumn(name="service_id", referencedColumnName="id"))
    private List<Service> services = new ArrayList<>();

    public User(String name,String status){
        this.name = name;
        this.status = status;
    }

    //Ajouter des services à utiliser
    public void addService(Service service){
        services.add(service);
    }
}

Maître de service


@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
@Entity
@Table
public class Service implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String status;

    public Service(String name,String status) {
        this.name = name;
        this.status = status;
    }
}

processus d'inscription


User user = entityManager.find(User.class,<Identifiant d'utilisateur>);
Service service = entityManager.find(Service.class,<ID de service à utiliser>);
user.addService(service);
entityManager.persist(user);

Enregistrement lorsqu'il y a un élément autre que la clé composée

Ajoutez «Date de début» au tableau des services d'utilisation.

1.png

Dans ce cas, la date de début d'utilisation ne peut pas être enregistrée uniquement avec `` @ JoinTable '', donc une classe d'entité sera créée en tant que service d'utilisation.

Service utilisé


@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
@Entity
@Table(name = "user_service")
public class UserService implements Serializable {

    @EmbeddedId
    private PrimaryKey pk;
    
    @Column(name = "begin_date")
    private LocalDate beginDate;

    @ManyToOne
    @MapsId("userId")
    private User user;

    @ManyToOne
    @MapsId("serviceId")
    private Service service;

    public UserService(User user, Service service,LocalDate beginDate) {
        this.user = user;
        this.service = service;
        this.beginDate = beginDate;
    }

    @Getter
    @NoArgsConstructor
    @Embeddable
    public static class PrimaryKey implements Serializable {

        @Column(name = "user_id")
        private Long userId;

        @Column(name = "service_id")
        private Long serviceId;
    }
}

L'important ici est `` @ MapsId ''. Spécifiez le nom de champ défini dans la classe PrimaryKey que vous souhaitez mapper à l'argument. Cela associe la classe d'entité à la clé composite.

Modifiez également le maître utilisateur. À l'origine, j'ai pu obtenir le service que j'utilise auprès du maître des utilisateurs. Obtenez-le via votre classe de service.

Maître des utilisateurs


@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = {"id"})
@Entity
@Table
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String status;

    @OneToMany(mappedBy = "user")
    private List<UserService> services = new ArrayList<>();

    public User(String name,String status){
        this.name = name;
        this.status = status;
    }
    
    //Ajouter des services à utiliser
    public void addService(Service service){
        services.add(new UserService(this, service, LocalDate.now()));
    }

    //Je retournerai une liste de services au lieu d'une liste de tables d'intersection
    public List<Service> getServices(){
        return services.stream().map(UserService::getService).collect(Collectors.toList());
    }
}

Exemple de processus d'inscription


User user = entityManager.find(User.class,<Identifiant d'utilisateur>);
Service service = entityManager.find(Service.class,<ID de service à utiliser>);
user.addServices(service);
entityManager.persist(user);

Recommended Posts

[JPA] Comment enregistrer lorsque vous avez des éléments autres que des clés dans la table d'intersection liés à ManyToMany
Comment afficher la valeur lorsqu'il y a un tableau dans le tableau
[Rails] Comment enregistrer plusieurs enregistrements dans la table intermédiaire avec une association plusieurs-à-plusieurs
Comment changer le processus en fonction de la liste appuyée lorsqu'il y a plusieurs ListViews
Comment régler chrony lorsque le temps change dans CentOS7
Que faire lorsque les modifications du servlet ne sont pas reflétées
[jOOQ] Comment utiliser CASE WHEN dans la clause WHERE / AND / OR
(Spring-data-jpa) Comment obtenir POJO (autre que la classe d'entité) à l'aide de JPA2.1
Comment résoudre l'erreur inconnue apparue lors de l'utilisation de slf4j en Java
Pourquoi s'arrête-t-il lorsque je débogue dans Eclipse et qu'il n'y a pas de points d'arrêt? Liens relatifs à
Comment trouver le nombre total de pages lors de la pagination en Java
Comment contraindre l'action de la destination de transition lorsqu'elle n'est pas connectée
Comment référencer une colonne lors du remplacement de la méthode de nom de colonne dans ActiveRecord