HibernateJpaConfiguration java.lang.NullPointerException, когда я использую 2 отношения ManyToMany

У меня есть следующие таблицы:

  • Пользователь

HibernateJpaConfiguration java.lang.NullPointerException, когда я использую 2 отношения ManyToMany

  • роль

HibernateJpaConfiguration java.lang.NullPointerException, когда я использую 2 отношения ManyToMany

  • номер

HibernateJpaConfiguration java.lang.NullPointerException, когда я использую 2 отношения ManyToMany

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) и многие другие. Но ничто не поможет мне решить эту проблему.

Проверьте мой ответ на русо

Antonio112009 23.06.2019 13:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
2 667
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема, которую я вижу, заключается в том, что вы неправильно установили атрибуты 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" (в каждом(!) проекте)

Valentyn Hruzytskyi 23.06.2019 08:31

@ValentynHruzytskyi Проверьте это статья

Antonio112009 23.06.2019 13:40

Правда, исключение отложенной инициализации возникает при попытке доступа к отношениям, которые не были выбраны специально. Вам нужно будет научиться извлекать отношения, к которым вы хотите получить доступ. Я видел хорошие вещи с использованием @EntityGraph в репозиториях, чтобы справиться с этим.

K.Nicholas 23.06.2019 16:40

Другие вопросы по теме