Errro de identificação de instância quando alterada de 1 para 2

Olá, estou com este erro:
identifier of an instance of br.com.empresa.entrevista.data.entity.Pais was altered from 1 to 2

OU seja, não consigo mudar um País de um Estado.

Tenho que fazer mudanças na entidade Pais não é isso? Mas Veja minha entidade:

Pais.java

@Getter
@Setter
@Entity
@Table(name = "Pais")
@SQLDelete(sql = "UPDATE pais SET ativo = 0 WHERE id = ?")
@Where(clause = "ativo = 1")
public class Pais extends BaseEntity {

	private String nome;
	private String sigla;
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "pais")	
	private Set<Estado> estados;
	
}

Meu PaisResource.java:

@RestController 
@RequestMapping("/api/pais") 
public class PaisResource {
		
	@Autowired
	private PaisRepository repository;
	@Autowired
	private PaisResourceMapper mapper;
	@Autowired
	private PaisService service; 

	@GetMapping(produces = { MediaType.APPLICATION_JSON_VALUE })
	public ResponseEntity<PageDto<PaisDTO>> getPageWithQuery(@QuerydslPredicate(root = Pais.class ) Predicate predicate, Pageable pageble) {
		return ResponseEntity.ok(convertToPageDto(predicate, pageble));
	}
	
	@PostMapping
	public ResponseEntity<PaisDTO> add(@Valid @RequestBody PaisDTO dto) throws Exception {
		Pais entity = this.mapper.fromDto(dto);
		
		service.validateAdd(dto, entity);

    	entity = repository.save(entity);
    	
    	ResponseEntity<PaisDTO> re = ResponseEntity.ok(this.convertToDto(entity));
    	
    	return re;
				
	}

	@GetMapping(value = "/{id}")
	public ResponseEntity<PaisDTO> get(@PathVariable Integer id) {
		return ResponseEntity.ok(convertToDto(repository.findById(id).get()));
	}

	@PutMapping(value = "/{id}")
	public ResponseEntity<PaisDTO> update(@Valid @RequestBody PaisDTO dto, @PathVariable Integer id) throws Exception {
		
		Optional<Pais> entity = repository.findById(id);
		if (entity.isPresent()) {
			
			this.mapper.merge(entity.get(), dto);

			service.validateUpdate(dto, entity.get());

			Pais mergedEntity = repository.save(entity.get());
        	
        	ResponseEntity<PaisDTO> re = ResponseEntity.ok(this.convertToDto(mergedEntity));
        	
			return re;
		} else {
			throw new RuntimeException();
		}
		
	}	

	@DeleteMapping(value = "/{id}")
	public void delete(@PathVariable Integer id) throws Exception {
		
		service.validateDelete(id);
		
		repository.deleteById(id);
		
	}
	
	private PageDto<PaisDTO> convertToPageDto(Predicate predicate, Pageable pageble) {
		Page<Pais> pageEntity = repository.findAll(predicate, pageble);
		
		return new PageDto<PaisDTO>(StreamSupport.stream(pageEntity.spliterator(), false).map(this::convertToDto)
				.collect(Collectors.toList()), pageEntity.getTotalElements());
	}	   
	
	private PaisDTO convertToDto(Pais entity) {
		return mapper.toDto(entity);
	}
		
}

Veja o front:

@Jonathan_Medeiros você teria alguma ideia? Desculpe te incomodar cara, mas se puder me ajudar agradeço. Até o @pmlm é um cara também gente boa que vez ou outra me dá uma ideia…:+1:

O problema em si está em estado e não no país, certo?

Você está tentando atualizar dados de um estado e não pais, pelo menos é o que me parece!

Compartilha suas classes de estado, controller e entidade!

Isso, me equivoquei, é Estado mesmo. Veja aí @Jonathan_Medeiros por favor:

Estado.java:

@Getter
@Setter
@Entity
@SQLDelete(sql = "UPDATE estado SET ativo = 0 WHERE id = ?")
@Where(clause = "ativo = 1")
public class Estado extends BaseEntity {

	private String nome;
	private String sigla;	
	private Double populacao;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(nullable = false)
	private Pais pais;
	
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "estado")	
	private Set<Cidade> cidades;
	
	
}

EstadoRepository.java

@Repository 
@JaversSpringDataAuditable
public interface EstadoRepository extends DefaultRepository<Integer, Estado, QEstado> { 

}

EstadoResource.java

@RestController 
@RequestMapping("/api/estado") 
public class EstadoResource {
	
@Autowired
private EstadoRepository repository;
@Autowired
private EstadoResourceMapper mapper;
@Autowired
private EstadoService service; 

@GetMapping(produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<PageDto<EstadoDTO>> getPageWithQuery(@QuerydslPredicate(root = Estado.class ) Predicate predicate, Pageable pageble) {
	return ResponseEntity.ok(convertToPageDto(predicate, pageble));
}
	
@GetMapping(value = "/{id}")
public ResponseEntity<EstadoDTO> get(@PathVariable Integer id) {
	return ResponseEntity.ok(convertToDto(repository.findById(id).get()));
}

@PostMapping
public ResponseEntity<EstadoDTO> add(@Valid @RequestBody EstadoDTO dto) throws Exception {
	Estado entity = this.mapper.fromDto(dto);
	
	service.validateAdd(dto, entity);

	entity = repository.save(entity);
	
	ResponseEntity<EstadoDTO> re = ResponseEntity.ok(this.convertToDto(entity));
	
	return re;
			
}

@PutMapping(value = "/{id}")
public ResponseEntity<EstadoDTO> update(@Valid @RequestBody EstadoDTO dto, @PathVariable Integer id) throws Exception {
	
	Optional<Estado> entity = repository.findById(id);
	if (entity.isPresent()) {
		
		this.mapper.merge(entity.get(), dto);

		service.validateUpdate(dto, entity.get());

		Estado mergedEntity = repository.save(entity.get());
    	
    	ResponseEntity<EstadoDTO> re = ResponseEntity.ok(this.convertToDto(mergedEntity));
    	
		return re;
	} else {
		throw new RuntimeException();
	}
	
}	

@DeleteMapping(value = "/{id}")
public void delete(@PathVariable Integer id) throws Exception {
	
	service.validateDelete(id);
	
	repository.deleteById(id);
	
}

private PageDto<EstadoDTO> convertToPageDto(Predicate predicate, Pageable pageble) {
	Page<Estado> pageEntity = repository.findAll(predicate, pageble);
	
	return new PageDto<EstadoDTO>(StreamSupport.stream(pageEntity.spliterator(), false).map(this::convertToDto)
			.collect(Collectors.toList()), pageEntity.getTotalElements());
}	   

private EstadoDTO convertToDto(Estado entity) {
	return mapper.toDto(entity);
}

}

EstadoService.java:

public interface EstadoService {

	void validateDelete(Integer id) throws AppException;
	void validateUpdate(@Valid EstadoDTO dto, Estado entity) throws AppException;
	void validateAdd(@Valid EstadoDTO dto, Estado entity) throws AppException;
	
}

Perfeito!

Pelo que me parece você não busca país no DB, certo?

Para atualizar o país contido no estado primeiro você precisa colocá-lo em um estado gerenciável pelo JPA, ou seja, dar ao JPA conhecimento do objeto que está sendo modificado, no caso do update isso é feito através de uma simples busca de país no banco de dados e setá-lo na entidade.

Busco… Veja:

guj3

Veja o GET pelo postman:

Perceba, não digo que o registro não exista em sua base de dados, até porquê ele está sendo carregado em tela, mas sim que você não faz a busca dele antes de atualizar o estado, compreende?

No método de atualizar o estado teria que ter algo mais ou menos assim:

Pais pais = paisRepository.findById(dto.getPais().getId());
estadoEntity.setPais(pais);

Olá @Jonathan_Medeiros eu não consegui cara… Este não seria o meu método update de estado?

  @PutMapping(value = "/{id}")
    	public ResponseEntity<EstadoDTO> update(@Valid @RequestBody EstadoDTO dto, @PathVariable Integer id) throws Exception {
		
		
		Optional<Estado> entity = repository.findById(id);
		if (entity.isPresent()) {
			
			this.mapper.merge(entity.get(), dto);

			service.validateUpdate(dto, entity.get());

			Estado mergedEntity = repository.save(entity.get());
        	
        	ResponseEntity<EstadoDTO> re = ResponseEntity.ok(this.convertToDto(mergedEntity));
        	
			return re;
		} else {
			throw new RuntimeException();
		}
		
	}	

Então, quando insiro

    @PutMapping(value = "/{id}")
	public ResponseEntity<EstadoDTO> update(@Valid @RequestBody EstadoDTO dto, @PathVariable Integer id) throws Exception {
		
Pais pais = paisRepository.findById(dto.getPais().getId());
estadoEntity.setPais(pais);
		
		Optional<Estado> entity = repository.findById(id);
		if (entity.isPresent()) {
			
			this.mapper.merge(entity.get(), dto);

			service.validateUpdate(dto, entity.get());

			Estado mergedEntity = repository.save(entity.get());
        	
        	ResponseEntity<EstadoDTO> re = ResponseEntity.ok(this.convertToDto(mergedEntity));
        	
			return re;
		} else {
			throw new RuntimeException();
		}
		
	}	

Ele diz que tenho que criar variáveis relacionadas. Daí eu crio e vira um loop de erros. Você poderia me esclarecer no que estou errando?

Está dando errado porquê você só copiou e colou, eu escrevi para te servir como referência para você implementar no seu código!

E no caso essa parte da implementação ficaria após o if que verifica se o estado existe!

1 curtida