我尝试了几乎所有我在SO中找到的内容,以及另一个关于使用Hibernate创建一对一关系的网站教程。
所以,我有两个模型,这里是最后的修改,比如我在之前的测试中也删除了@MapsId注释。
Usuario:
@Entity
@Table(name="usuarios")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Usuario {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="usuarios_id_seq")
@SequenceGenerator(name="usuarios_id_seq", sequenceName="usuarios_id_seq", allocationSize=1)
@Column(name="id")
private Long id;
@ManyToOne
@JoinTable(name="roles_usuarios", joinColumns={@JoinColumn(name="usuarios_id", referencedColumnName="id")}, inverseJoinColumns={@JoinColumn(name="roles_id", referencedColumnName="id")})
private Rol rol;
@OneToOne(cascade = CascadeType.ALL, mappedBy="usuario")
private Cliente cliente;
Cliente:
@Entity
@Table(name="clientes")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Cliente {
@Id
//@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="clientes_id_seq")
//@SequenceGenerator(name="clientes_id_seq", sequenceName="clientes_id_seq", allocationSize=1)
//@Column(name="id")
private Long id;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="usuario_id", referencedColumnName="id")
@MapsId
private Usuario usuario;
Cliente Controller:
@PostMapping("/")
public ResponseEntity<Void> postCliente(@RequestBody Cliente cliente, UriComponentsBuilder ucBuilder) {
if( clienteService.isClienteExist(cliente) ){
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
clienteService.save(cliente);
HttpHeaders headers = new HttpHeaders();
headers.setLocation( ucBuilder.path("/{id}").buildAndExpand(cliente.getId()).toUri() );
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
客户服务:
@Override
public Cliente save(Cliente cliente) {
Cliente clt = new Cliente();
clt.setUsuario(cliente.getUsuario());
clt.setRazonSocial(cliente.getRazonSocial());
clt.setRfc(cliente.getRfc());
clt.setDireccion(cliente.getDireccion());
clt.setEmail(cliente.getEmail());
clt.setTelefono(cliente.getTelefono());
clt.setContacto(cliente.getContacto());
clt.setTelContacto(cliente.getTelContacto());
clt.setEmailContacto(cliente.getEmailContacto());
return clienteRepository.save(clt);
}
如果你注意到我与Rol表有多对一的关系可以正常工作,但是当我在OneToOne中传递信息时我将其作为JSON传递它产生:传递给persist的分离实体:com .swargos.entities.Usuario
IDK,如果我缺少一些注释,或者是在运行spring应用程序时创建了数据库。
答案 0 :(得分:1)
我提供了一个有点合格的猜测,因为你没有包含显示你如何调用持久性的代码。
错误意味着您传递给persist()的Usuario实例已经有一个主键,但它不是该持久化上下文的托管实体,请参阅此处Entity Object lifecycle
我的猜测是Usuario实例由另一个EntityManager加载,然后json序列化到前端,然后发回到后端,你需要在Cliente上设置它(因为你在两者中都有级联方向也可能是在Usuario上设置的Cliente)。每次在一个持久性上下文中加载实体,并且您想要将其保存在另一个持久性上下文中时,您必须调用em.merge()
或者必须调用em.find()
将其加载到其中(然后设置更改)
JPA并不神奇,实体的生命周期和管理它们的持久化上下文已经明确定义,除非开发人员理解这些机制如何工作,否则将浪费大量时间来反对框架。
只有当Cliente为其主键使用@EmbeddedId时才应使用@MapsId,这似乎不是这种情况。