Spring JPA嵌套异常:传递给persist的分离实体

时间:2017-01-16 23:55:02

标签: spring hibernate jpa

我尝试了几乎所有我在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应用程序时创建了数据库。

1 个答案:

答案 0 :(得分:1)

我提供了一个有点合格的猜测,因为你没有包含显示你如何调用持久性的代码。

错误意味着您传递给persist()的Usuario实例已经有一个主键,但它不是该持久化上下文的托管实体,请参阅此处Entity Object lifecycle

我的猜测是Usuario实例由另一个EntityManager加载,然后json序列化到前端,然后发回到后端,你需要在Cliente上设置它(因为你在两者中都有级联方向也可能是在Usuario上设置的Cliente)。每次在一个持久性上下文中加载实体,并且您想要将其保存在另一个持久性上下文中时,您必须调用em.merge()或者必须调用em.find()将其加载到其中(然后设置更改)

JPA并不神奇,实体的生命周期和管理它们的持久化上下文已经明确定义,除非开发人员理解这些机制如何工作,否则将浪费大量时间来反对框架。

只有当Cliente为其主键使用@EmbeddedId时才应使用@MapsId,这似乎不是这种情况。