Spring Boot REST один к одному - POST или PUT? - PullRequest
0 голосов
/ 21 июня 2020

Я разрабатываю Spring Boot REST api, и теперь я столкнулся с некоторыми logical problem.

Итак, у меня есть сущность «A», которая имеет однозначные отношения с сущностью «B». Первоначально объект «A» отправляется на POST без объекта «B» (-> так что отношение равно null).

Поэтому, когда я хочу добавить объект «B», я должен просто отправить его POST или PUT / PATCH объект "A" с объектом "B"?

Ответы [ 2 ]

1 голос
/ 21 июня 2020

Рассмотрим объекты A и B и взяли поля firstName и lastName:

@Entity
public class A {

    @Id
    private Integer id;

    private String firstName;

    @OneToOne(mappedBy = "a")
    private B b; 
}

@Entity
public class B {

    @Id
    private Integer id;
 
    private String lastName;

    @OneToOne
    private A a;
}

Репозитории:

@Repository 
 public interface ARepo extends JpaRepository<A,Integer> {
}
@Repository
 public interface BRepo extends JpaRepository<B,Integer> {
}

давайте используем @postContruct для сохранения некоторых данных в объекте A

@PostConstruct
void init(){
    A a = new A(1,"ABCD");
    aRepo.save(a);
}

контроллер для сохранения объекта B:

 @PostMapping("/saveB")
 public String save(@RequestBody B b){
    bRepo.save(b);
    return "ok";
 }

и json для сохранения объекта B:

{"id": 1, "lastName": "xyz", "a": {"id": 1}}

Насколько я понимаю, если мы сохраняем объект из репозитория B, нам нужно использовать @PostMapping (вставляется новая строка), или мы можем использовать репозиторий A для сохранения объекта B, потому что здесь отображение является двунаправленным, с помощью @PutMapping (уже данные A выходят в базе данных, нам нужно обновить их, добавив данные B)

0 голосов
/ 21 июня 2020

Нет никакой связи между сохранением объекта в БД с использованием ORM, например, Hibernate и POST/PUT/PATCH, которые являются HTTP глаголами. Пожалуйста, не запутайтесь.

Предполагая, что у вас есть объекты A и B, определенные как двунаправленная связь один-к-одному (по умолчанию атрибут ассоциации (в данном случае один-к-одному) optional равен true):

@Entity
public class A implements Serializable {

    private static final long serialVersionUID = -7174277851973636756L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(mappedBy = "a") //If you add optional = false, it will not work
    B b;

    //And so on
}


@Entity
public class B implements Serializable {

    private static final long serialVersionUID = -6581935686158784727L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne
    @JoinColumn(name = "id") //You need this, else it will look for "a_id" column(foreign_key) in Class/Table B.
    A a;

   //And so on
}

И ARepository и BRepository следующим образом:

public interface ARepository extends CrudRepository<A, Long> {

}

public interface BRepository extends CrudRepository<B, Long> {

}

Вы можете просто сделать сначала:

@Autowired
private ARepository aRepository;

A a = new A();
aRepository.save(a);
    

А потом:

@Autowired
private BRepository bRepository;

B b = new B();
bRepository.save(b);

Эквивалентные SQL:

insert 
into
    a
    (id) 
values
    (?)

insert 
into
   b
    (id) 
values
    (?)

Примечание. Если объект уже существует, save выполнит update вместо insert, но поскольку мы используем автозапуск сгенерированный идентификатор, он всегда будет делать insert.

...