Pessoal, fiz um mapeamento bidireccional na minha api RESTful. O problema é que na tabela que tem a chave estrangeira, essa chave estrangeira está null. Estou utilizando o postman para fazer o post. Gostaria da ajuda de vcs para resolver isso. Obrigado. Seguem os códigos.
@Entity
@Table(name="ger_grupo_item")
public class GrupoItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="git_id")
private Long id;
@OneToMany(mappedBy = "grupoItem", orphanRemoval = true, cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private List<SubGrupoItem> subGruposItens;
@Entity
@Table(name="ger_subgrupo_item")
public class SubGrupoItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="sbg_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="git_id")
private GrupoItem grupoItem;
Controller
@RestController
@RequestMapping({"/api/v1/grupoitem"})
public class GrupoItemController {
@PostMapping
//@Secured({ "ROLE_ADMIN" })
public ResponseEntity post(@RequestBody GrupoItem grupoItem) {
GrupoItemDTO gI = service.insert(grupoItem);
return ResponseEntity.ok().build();
}
Mas o que tem a ver a parte rest com o banco de dados?
A questão da PK/FK é específica do banco de dados. Serializar ou não um ou outro atributo não depende disso.
ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [git_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.postgresql.util.PSQLException: ERROR: null value in column “git_id” violates not-null constraint
Detalhe: Failing row contains (7, null, subnometeste).
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2497)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2233)
O problema de você usar um relacionamento bidirecional é que você é obrigado a setar, em todos os envolvidos, todos os envolvidos. Entendeu?
Por exemplo, considere as classes A e B
public class A{
private List<B> bs;
}
public class B {
private List<A> as;
}
Você está fazendo algo como:
A a = new A();
a.getBs().addAll(bs);
E está tentando persistir.
Ocorre que você também precisa fazer isso:
for(B b : bs) {
b.getAs().add(a);
}
Ou seja, em cada elemento de A você deve incluir todos os elementos de B que forem necessários. E, em cada elemento de B associado a A, você precisa adicionar a própria instância de A.
Entendi sim. Consegui fazer. É uma boa prática fazer o post nesse controller ? Ou seria melhor eu fazer o post no controller que tem a FK ? O que vc acha ? Poderia me explicar melhor a parte do for? Eu entendi o q tem q ser feito mas não consegui implementar o for. Obrigado desde já. Ficou assim:
@PostMapping
public ResponseEntity post(@RequestBody GrupoItem grupoItem) {
List<SubGrupoItem> listaSubGrupoItem = new ArrayList<>();
SubGrupoItem subGrupoItem = new SubGrupoItem();
subGrupoItem.setGrupoItem(grupoItem);
listaSubGrupoItem.add(subGrupoItem);
//criar loop
grupoItem.setSubGrupoItens(listaSubGrupoItem);
GrupoItemDTO gI = service.insert(grupoItem);
URI location = getUri(gI.getId());
return ResponseEntity.created(location).build();
}
O controller é o cara responsável por receber requisições referentes a um elemento específico. Se você está misturando ambos, seria interessante isolar. Mas, aí é uma necessidade de negócio específica da tua aplicação