Hibernate OneToOne попытался присвоить идентификатор из нулевого свойства один к одному

Я пытаюсь создать отношение один к одному между двумя объектами, где на дочерний элемент ссылается родительский идентификатор как внешний ключ. Вот мои 2 объекта:

@Entity
@Table(name = "users")
public class User extends PanacheEntityBase implements Serializable {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
    String id;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL , optional = false)
    Profile profile;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }
}

а также

@Entity
@Table(name = "profiles")
public class Profile extends PanacheEntityBase implements Serializable {

    @GenericGenerator(name = "generator", strategy = "foreign",  parameters = @Parameter(name = "property", value = "user"))
    @Id
    @GeneratedValue(generator = "generator")
    @Column(name = "user_id")
    String id;

    @OneToOne
    @MapsId
    @JoinColumn(name = "user_id")
    User user;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

При сохранении я создаю объект и сохраняю его:

    User user = new User();
    Profile profile = new Profile();
    user.setProfile(profile);
    userRepository.persist(user);

но я получаю эту ошибку

org.jboss.resteasy.spi.UnhandledException: javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: попытка присвоить идентификатор из нулевого свойства «один к одному» [com.myne.entities.Profile.user]

Что я делаю неправильно?


person user3353167    schedule 04.11.2020    source источник
comment
Вы пробовали делать profile.setUser(user)?   -  person Ran    schedule 04.11.2020
comment
да, но он производит бесконечный рекурсивный вызов   -  person user3353167    schedule 04.11.2020
comment
Что такое новый пользователь? Вы инициализируете поле пользователя, а не newuser   -  person Ran    schedule 04.11.2020
comment
Ваша настройка немного странная, является ли PK профиля идентификатором пользователя?   -  person Smutje    schedule 04.11.2020
comment
@По моей ошибке это пользователь.   -  person user3353167    schedule 04.11.2020
comment
@Smutje идея в том, что пользователь и профиль имеют один и тот же pk, если только это невозможно и есть другие подходы.   -  person user3353167    schedule 04.11.2020
comment
Можете ли вы попытаться удалить все аннотации из Profile.id, кроме @Id и @Column? Я не думаю, что @GenericGenerator и GeneratedValue необходимы (см. также thorben-janssen.com/)   -  person Smutje    schedule 04.11.2020
comment
@Smutje, к сожалению, даже точно следуя тому, что он делает, я все еще сталкиваюсь с той же проблемой.   -  person user3353167    schedule 04.11.2020
comment
Хорошо, возможно, это как-то связано с вашим org.hibernate.id.UUIDGenerator, но это выходит за рамки моих знаний о JPA (или Hibernate в этом случае) :-)   -  person Smutje    schedule 04.11.2020


Ответы (1)


Итак, после дополнительных исследований я, наконец, смог справиться с проблемой. Я использовал гибрид между этими 3 сообщениями

https://howtodoinjava.com/hibernate/hibernate-one-to-one-mapping/

https://stackoverflow.com/a/52010963/3353167

https://stackoverflow.com/a/18622821/3353167

Как было предложено в первом посте, использование @MapsId позволит hibernate узнать, что дочерний объект будет использовать родительский идентификатор. Поэтому я изменил свои классы на:

@Entity
@Table(name = "users")
public class User extends PanacheEntityBase implements Serializable {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
    String id;

    @OneToOne
    @MapsId
    Profile profile;

    ...

А также

@Entity
@Table(name = "profiles")
public class Profile extends PanacheEntityBase implements Serializable {

    @Id
    @Column(name = "user_id")
    String id;
    
    // removed the User Column
    ...

Затем проблема возникает из-за Hibernate с использованием GenerationType.Auto, как это предлагается в третьем посте. Поэтому, чтобы указать Hibernate генерировать вместо этого UUID, я последовал примеру во втором сообщении и изменил идентификатор профиля, чтобы он выглядел так:

@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "user_id", updatable = false, nullable = false)
@Id
String id; 

...

Оно работало завораживающе. Я надеюсь, что это поможет любому, кто столкнется с той же проблемой в будущем

person user3353167    schedule 04.11.2020
comment
Извините, но значит ли это, что у вас не может быть двунаправленной связи между пользователем и профилем? Например: у пользователя есть профиль, но вы не можете получить пользователя, если у вас есть только профиль? - person Voronin; 29.07.2021