Spring boot / Spring data jpa - как обновить связанный объект? - PullRequest
1 голос
/ 15 января 2020

У меня есть следующие объекты:

@Entity
@Table(name = "profile")
public class Profile {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    private ProfileContacts profileContacts;

...

}

и

@Entity
@Table(name = "profile_contacts")
public class ProfileContacts {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

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

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

}

Я пытаюсь обновить его, отправив это JSON с обновлением на контроллер REST:

{
        "id": 1,
        "description": "an update",
        "profileContacts": {
            "firstName": "John",
            "lastName": "Doe"
        }
 }

поэтому в конце он вызывает

profileRepository.save(profile);

, где profileRepository является экземпляром класса ProfileRepository:

public interface ProfileRepository extends JpaRepository<Profile, Long> {
}

, который является spring-data-jpa интерфейсом.

Но каждый раз после такого обновления он обновляет profile таблицу, но добавляет новую строку в profile_contacts таблицу (таблицу, которая соответствует ProfileContacts сущности) вместо обновления существующих. Как я могу добиться обновления?

Ответы [ 4 ]

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

Согласно вашей JSON структуре. Да, каждый раз будет создаваться новая запись profileContacts.

Проблема каждый раз при сохранении profile передаваемой вами сущности "id": 1, что означает, что Hibernate может идентифицировать сущность по этому значению id (основной ключ), но для отображения profileContacts вы не отправляете id, поэтому Hibernate, учитывая, что он каждый раз имеет новую сущность.

Чтобы обновить вашу сущность profileContacts, обязательно передайте ее идентификатор.

Пример:

{ 
"id": 1,
 "description": "an update", 
"profileContacts": {
"id" : yourEntityId
 "firstName": "John", 
"lastName": "Doe" 
}
 }
2 голосов
/ 15 января 2020

Что ж, это ожидаемое поведение.

Вы не говорите hibernate об обновлении profileContacts.

Чтобы инфраструктура могла его обновить, вам нужно отправить Первичный ключ profileContact - в вашем случае это ProfileContacts#id.

Примерно так:

{
  "id": 1,
  "description": "an update",
  "profileContacts": {
    "id": 1
    "firstName": "John",
    "lastName": "Doe"
  }
}
1 голос
/ 15 января 2020

Хорошо, я вижу проблему. Как указал @Matheus Cirillo, вы должны указать hibernate для обновления строки.

Теперь, как вы говорите hibernate для обновления строки - предоставив первичный ключ существующей строки.

Но создания объекта с набором первичного ключа недостаточно. Вам нужно, чтобы этот класс сущностей был присоединен к менеджеру сущностей и контексту постоянства.

Вы можете иметь что-то вроде

//This attaches the entity to the entity manager
ProfileContacts existingProfileContacts = profileContactRepository.getOne(2);
Profile profile = new Profile();
....
....
profile.setProfileContacts(existingProfileContacts);
profileRepository.save(profile);

Надеюсь, это поможет.

1 голос
/ 15 января 2020
Need to specify the join column in the parent Entity.
@Entity
@Table(name = "profile")
public class Profile {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

@OneToOne(cascade = CascadeType.ALL)
**@JoinColumn(name = "id")** //
private ProfileContacts profileContacts;

...

}
Now when you try to save Profile entity it will save the child entity also. 

А также необходимо включить Id в запрос jason для дочерней сущности также {"id": 1, "description": "a update", "profileContacts": { "id": 1,"firstName": "John", "lastName": "Doe"}}

...