У меня есть следующие таблицы:
user + role и user + rooms должны быть сопоставлены @ManyToMany таблицей.
Когда я создал сущности user и role, все работало хорошо,
Пользователь
@Entity
@Table(name = "user")
public class User extends BaseEntity {
//.........
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}
)
private Set<UserRole> roles;
Пользовательские роли
@Entity
@Table(name = "roles")
public class UserRole extends AutoIncrementIdBaseEntity {
//....
@ManyToMany(mappedBy = "roles")
private Set<User> users;
room:Пользователь
@ManyToMany
@JoinTable(name = "user_room",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "room_id", referencedColumnName = "id")}
)
private Set<Room> rooms;
Номер
@Entity
@Table(name = "room")
public class Room extends BaseEntity{
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator",
parameters = {
@org.hibernate.annotations.Parameter(
name = "uuid_gen_strategy_class",
value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
)
}
)
@Column(name = "id")
private String id;
@ManyToMany(mappedBy = "rooms")
private Set<User> userList;
У меня есть следующее исключение:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NullPointerException
Я уже пробую использовать LAZY, EAGER методы, @Proxy(lazy = false) и многие другие. Но ничто не поможет мне решить эту проблему.





Основная проблема, которую я вижу, заключается в том, что вы неправильно установили атрибуты mappedBy=. Значение должно быть именем поля в сущности owning, например, rooms вместо room.
@ManyToMany(mappedBy = "rooms")
private Set<User> userList;
Кроме того, не используйте FetchType.EAGER без конкретного варианта использования, и я не знаю, что это за вариант использования. Это приведет только к головным болям. Вы должны создавать специальные запросы для извлечения отношений, когда они необходимы.
Когда ваша таблица Room имеет внешний ключ creator_id, тогда у вас есть отношение OneToMany, а не отношение ManyToMany. ManyToMany отношения должны использовать таблицу соединений для реализации. FK может реализовать только OneToMany отношения. Здесь вы также должны правильно установить аннотацию mappedBy.
@OneToMany(mappedBy = "creator")
private Set<Room> rooms;
а также
@ManyToOne
private User creator;
Аннотация mappedBy указывает объект-владелец.
The field that owns the relationship. Required unless the relationship is unidirectional.
Вы использовали bidirectional сопоставления, поэтому вы используете mappedBy аннотации. Значение владения сущностью - это сущность, которая отвечает за сохранение отношения. В вашем примере Room отвечает за сохранение отношения creator, а User отвечает за сохранение отношения user_role. Окончательный результат может быть
@Entity
public class User {
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}
)
private Set<Role> roles;
@OneToMany(mappedBy = "creator")
private Set<Room> rooms;
@Entity
public class Role {
@ManyToMany(mappedBy = "roles")
private Set<User> users;
@Entity
public class Room {
@ManyToOne
private User creator;
и простым примером использования его через spring-data-jpa может быть
Role r1 = new Role();
roleRepo.save(r1);
User u1 = new User();
// needed to persist relation
u1.setRoles(Collections.singleton(r1));
// added to improve accuracy
r1.setUsers(Collections.singleton(u1));
userRepo.save(u1);
Room m1 = new Room();
// needed to persist relation
m1.setCreator(u1);
// added to improve accuracy
u1.setRooms(Collections.singleton(m1));
roomRepo.save(m1);
Обратите внимание, что вы должны специально управлять обеими сторонами двунаправленной связи при использовании определенного экземпляра без его обновления:
The Java Persistence API requires the references to be set on both sides of the relationship. This means that you have to explicitly call b.setA(a) and a.setB(b).
Итак, u1.setRooms(Collections.singleton(m1)); и r1.setUsers(Collections.singleton(u1)); добавляется, чтобы текущие экземпляры пользователей и ролей имели точные коллекции комнат и пользователей. Если эти экземпляры будут повторно загружены из базы данных позже с новым вызовом JPA, что является типичным, то в этом не будет необходимости.
Спасибо!! Об использовании типа EAGER: когда я его не использую, я получаю что-то вроде "LazyInitializationError" (в каждом(!) проекте)
@ValentynHruzytskyi Проверьте это статья
Правда, исключение отложенной инициализации возникает при попытке доступа к отношениям, которые не были выбраны специально. Вам нужно будет научиться извлекать отношения, к которым вы хотите получить доступ. Я видел хорошие вещи с использованием @EntityGraph в репозиториях, чтобы справиться с этим.
Проверьте мой ответ на русо