HibernateJpaConfiguration java.lang.NullPointerException, когда я использую 2 отношения ManyToMany - PullRequest
0 голосов
/ 23 июня 2019

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

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

enter image description here

  • роль

enter image description here

  • комната

enter image description here

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;

UserRoles

@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: Ошибка при создании компонента с именем 'entityManagerFactory', определенным в ресурсе пути к классу [org / springframework / boot / autoconfigure / orm / jpa / HibernateJpaConfiguration.class]: сбой вызова метода init;вложенным исключением является java.lang.NullPointerException

Я уже пытаюсь использовать методы LAZY, EAGER, @Proxy(lazy = false) и многие другие.Но ничто не поможет мне решить эту проблему.

1 Ответ

1 голос
/ 23 июня 2019

Основная проблема, которую я вижу, заключается в том, что вы неправильно установили атрибуты mappedBy=. Значением должно быть имя поля в сущности owning, например, rooms вместо room.

@ManyToMany(mappedBy = "rooms")
private Set<User> userList;

Кроме того, не используйте FetchType.EAGER без конкретного варианта использования, и я не знаю, что это за вариант использования. Это приведет только к головным болям. Вы должны создавать конкретные запросы для извлечения отношений, когда они необходимы.

Если ваша таблица Room имеет внешний ключ creator_id, тогда у вас есть отношение OneToMany, а не ManyToMany. ManyToMany отношения должны использовать соединительную таблицу, чтобы быть реализованными. ФК может реализовать только отношения OneToMany. Здесь вы также должны правильно установить аннотацию mappedBy.

@OneToMany(mappedBy="creator")
private Set<Room> rooms;

и

@ManyToOne
private User creator;

В аннотации mappedBy указывается сущность-владелец.

Поле, которому принадлежат отношения. Требуется, если отношения не являются однонаправленными.

Вы использовали 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);

Обратите внимание, что вы должны специально управлять обеими сторонами двунаправленных отношений при использовании определенного экземпляра без его обновления:

Java Persistence API требует, чтобы ссылки были установлены на обеих сторонах отношения. Это означает, что вам необходимо явно вызвать b.setA (a) и a.setB (b).

И так u1.setRooms (Collections.singleton (m1)); и r1.setUsers (Collections.singleton (u1)); добавляется, чтобы у текущего экземпляра пользователя и роли были точные комнаты и коллекции пользователей. Если эти экземпляры будут перезагружены из базы данных позже с новым вызовом JPA, что типично, то в этом нет необходимости.

...