Mapping with an intersection table is a headache every time. This time, I will introduce the registration method when you have a non-composite key in the intersection table.
First, suppose you have an entity with the following relationships:
The saving method in this case is as follows.
User master
@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;
}
//Add services to use
public void addService(Service service){
services.add(service);
}
}
Service master
@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;
}
}
registration process
User user = entityManager.find(User.class,<User ID>);
Service service = entityManager.find(Service.class,<Service ID to use>);
user.addService(service);
entityManager.persist(user);
Add "Start date" to the usage service table.
In this case, since the usage start date cannot be saved only with `` `@ JoinTable```, the entity class will be created as a usage service.
Service used
@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;
}
}
The important thing here is @ MapsId
. Specify the field name defined in the PrimaryKey class that you want to map to the argument. This associates the entity class with the composite key.
Also modify the user master. Originally, I was able to get the service I am using from the user master, Make sure to get it via the service class you are using.
User master
@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;
}
//Add services to use
public void addService(Service service){
services.add(new UserService(this, service, LocalDate.now()));
}
//I'll return a list of services instead of a list of intersection tables
public List<Service> getServices(){
return services.stream().map(UserService::getService).collect(Collectors.toList());
}
}
Registration process sample
User user = entityManager.find(User.class,<User ID>);
Service service = entityManager.find(Service.class,<Service ID to use>);
user.addServices(service);
entityManager.persist(user);
Recommended Posts