внешний ключ не вставляется, когда используется одноранговое отображение в спящем режиме - PullRequest
0 голосов
/ 31 января 2020

У меня есть две следующие дисциплины

сущность пользователя

@Entity
@Table(name = "user")
@Getter
@Setter
public class UserEntity{

    @Id
    @GeneratedValue(strategy = GeneratedType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;

    @Column(name = "user_name")
    private String name;

    @OneToOne(Cascade=CascadeType.ALL, mappedBy="user")
    private UserAddressEntity addressEntity;
}

сущность адреса пользователя

@Entity
@Table(name = "user_address")
@Getter
@Setter
public class UserAddressEntity{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_id")
    private Long userId;

    @Column(name = "address")
    private String address;

    @OneToOne
    @JoinColumn(name = "user_id", nullable = false, referencedColumnName = "user_id")
    private UserEntity user;
}

Я сохраняю сущность пользователя следующим образом в классе обслуживания

@Service
public class UserService{

    @Autowired
    private UserRepository userRepository;

    public void saveUser(){
        UserEntity userEntity=new UserEntity();
        UserAddressEntity userAddressEntity=new UserAddressEntity();

        //logic here

        userEntity.setAddressEntity(userAddressEntity);
        userRepository.save(userEntity);
    }
}

После сохранения сущности user_id столбец не сохраняется в таблице user_address . Это значение сохранено как нулевое. Кажется, я не могу найти, где проблема.

РЕДАКТИРОВАТЬ: Я добавил после сущностей после ответа, указанного в комментариях, но я получаю эту ошибку

Infinite recursion (StackOverflowError)

@Entity
@Table(name = "user")
@Getter
@Setter
public class UserEntity{

    @Id
    @GeneratedValue(strategy = GeneratedType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;

    @Column(name = "user_name")
    private String name;

    @OneToOne(Cascade=CascadeType.ALL, mappedBy="user")
    private UserAddressEntity addressEntity; 

    //added this
    public void setAddressEntity(UserAddressEntity addressEntity){
        if (!addressEntity.equals(this.addressEntity)){
            this.addressEntity=addressEntity;
            addressEntity.setUser(this);
        }

    }
@Entity
@Table(name = "user_address")
@Getter
@Setter
public class UserAddressEntity{
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_id")
    private Long userId;

    @Column(name = "address")
    private String address;

    @OneToOne
    @JoinColumn(name = "user_id", nullable = false, referencedColumnName = "user_id")
    private UserEntity user;

    //added this
    public void setUser(UserEntity user){
        if (!user.equals(this.user){
            this.user=user;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 31 января 2020

Вам необходимо правильно установить отношения в UserService.saveUser():

 userEntity.setAddressEntity(userAddressEntity);
 userAddressEntity.setUser(userEntity);

Кроме того, используйте обычные методы получения / установки, нет необходимости добавлять туда логи c.

0 голосов
/ 31 января 2020

Рекомендуемый / лучший способ отобразить @OneToOne - использовать @MapsId. При таком подходе вам вообще не нужна двунаправленная ассоциация.

Я бы посоветовал вам взглянуть на ссылку ниже, там у вас есть ответ на ваш вопрос с примером, как сохранять и сопоставлять объекты.

https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

...