Многие сами по себе с AssociationTable с EmbeddedId - Spring-Data-Jpa - PullRequest
0 голосов
/ 11 октября 2018

У меня возникли проблемы с Hibernate во время ассоциации ManyToMany: / Я хочу иметь пользователя со своими контактами.Таблица ассоциации используется для того, чтобы иметь дату создания ассоциации и ее статус (например, Активный, Неактивный и т. Д.)

  • Версия Hibernate: 5.2.17
  • Spring boot: 2.0.5

Мой класс ПОЛЬЗОВАТЕЛЬ:

@Entity(name = "user")
public class User implements Serializable {

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "assoc_user_user", joinColumns = {@JoinColumn(name = 
"id.myself.id")}, inverseJoinColumns = {@JoinColumn(name = 
"id.contact.id")})
private List<AssocUserUser> contacts;

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "assoc_user_user", joinColumns = {@JoinColumn(name = 
"id.contact.id")}, inverseJoinColumns = {@JoinColumn(name = 
"id.myself.id")})
private List<AssocUserUser> contactOf;

}

Мой класс ассоциации AssocUserUser:

@Entity(name = "assoc_user_user")
public class AssocUserUser implements Serializable {

private static final long serialVersionUID = 1L;

@EmbeddedId
private AssocUserUserId id;

@Column(name = "creation_date", nullable = false)
private LocalDateTime creationDate;

@Column(name = "status")
@Enumerated(EnumType.STRING)
private ContactStatusEnum status;

}

Мой класс EmbeddedId AssocUserUserId:

@Embeddable
public class AssocUserUserId implements Serializable {

private static final long serialVersionUID = 1L;

@ManyToOne
@JoinColumn(name = "user_id_myself", nullable = false)
private User myself;

@ManyToOne
@JoinColumn(name = "user_id_contact", nullable = false)
private User contact;

}

Моя ошибка:

Причина: org.hibernate.AnnotationException: AВнешний ключ ссылается на com ..... AssocUserUser от com ..... Пользователь имеет неправильный номер столбца.должно быть 2

1 Ответ

0 голосов
/ 11 октября 2018

Что ж, этот вопрос был задан и получен ответ на Связи Spring-Data-JPA ManyToMany с дополнительным столбцом , но я полагаю, что это немного отличается от собственной ссылки.Я не большой поклонник всех аннотаций JoinTable и JoinColumn, но только потому, что они обычно избыточны и, IMHO, предназначены для изменения значений по умолчанию.Мой ответ не включает эти аннотации, поэтому добавляйте их по мере необходимости.Обратите внимание, что для Spring-Data-Jpa вам нужны репозитории для каждой сущности, и поэтому вам нужен репозиторий для сущности ассоциации.Это отличается от одного менеджера сущностей в JPA.Это немного влияет на то, как вы справляетесь с Ассоциацией.Здесь мы сохраняем новые отношения, создавая и сохраняя новые AssocUserUser сущности.

То, как я сделал классы:

@Entity
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @OneToMany(mappedBy="myself")
    private Set<AssocUserUser> contacts;

@Entity
public class AssocUserUser {
    @EmbeddedId
    private AssocUserUserId id = new AssocUserUserId();
    @ManyToOne @MapsId("myselfId")
    private User myself;
    @ManyToOne @MapsId("contactId")
    private User contact;

@SuppressWarnings("serial")
@Embeddable
public class AssocUserUserId implements Serializable {
    private Long myselfId;
    private Long contactId;

и Repositories для обеих сущностей

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("select u from User u left outer join fetch u.contacts where u.id = :userId")
    User getContactsForUser(@Param("userId") Long userId);

public interface AssocUserUserRepository extends JpaRepository<AssocUserUser, AssocUserUserId> {

Как создать ассоциацию

private void update() {
    User user1 = new User();
    User contact1 = new User();
    userRepo.save(user1);
    userRepo.save(contact1);
    AssocUserUser assoc = new AssocUserUser();
    assoc.setMyself(user1);
    assoc.setContact(contact1);
    assocUserUserRepo.save(assoc);
}   

Как прочитать ассоциацию Unidirectional способом

private void read() {
    User me = new User();
    me.setId(1L);
    AssocUserUser assoc = new AssocUserUser();
    assoc.setMyself(me);
    List<AssocUserUser> contacts = assocUserUserRepo.findAll(Example.of(assoc));
    System.out.println(contacts.size());
}

И прочитать ассоциацию в Bidirectionalмода:

private void readBi() {
    User me = userRepo.getContactsForUser(1L);
    System.out.println(me.getContacts().size());
}

Как всегда, проверьте журналы:

create table assoc_user_user (contact_id bigint not null, myself_id bigint not null, primary key (contact_id, myself_id))
create table user (id bigint generated by default as identity, primary key (id))
alter table assoc_user_user add constraint FKaccetv956cu63fwiejjfrm0mi foreign key (contact_id) references user
alter table assoc_user_user add constraint FK1absxfuktrjnom8vwtjfqx5l0 foreign key (myself_id) references user

insert into user (id) values (null)
insert into user (id) values (null)
select assocuseru0_.contact_id as contact_1_0_0_, assocuseru0_.myself_id as myself_i2_0_0_ from assoc_user_user assocuseru0_ where assocuseru0_.contact_id=? and assocuseru0_.myself_id=?
select user0_.id as id1_1_0_ from user user0_ where user0_.id=?
select user0_.id as id1_1_0_ from user user0_ where user0_.id=?
insert into assoc_user_user (contact_id, myself_id) values (?, ?)

select assocuseru0_.contact_id as contact_1_0_, assocuseru0_.myself_id as myself_i2_0_ from assoc_user_user assocuseru0_ inner join user user1_ on assocuseru0_.myself_id=user1_.id where user1_.id=1
select user0_.id as id1_1_0_ from user user0_ where user0_.id=?
select user0_.id as id1_1_0_ from user user0_ where user0_.id=?

select user0_.id as id1_1_0_, contacts1_.contact_id as contact_1_0_1_, contacts1_.myself_id as myself_i2_0_1_, contacts1_.myself_id as myself_i2_0_0__, contacts1_.contact_id as contact_1_0_0__ from user user0_ left outer join assoc_user_user contacts1_ on user0_.id=contacts1_.myself_id where user0_.id=?
select user0_.id as id1_1_0_ from user user0_ where user0_.id=?
...