How to map entities with composite keys in JPA?

Asked

Viewed 5,444 times

1

I have a system where all tables in the database have a column empresa, which is part of PRIMARY KEY.

In the client table, I have a column id (autoincrement), which together with the empresa form a composite key, mapped as follows to the Java entity:

Entidade Cliente

@Entity
@Table(name = "CLIENTES")
public class ClienteEntity implements Serializable {

    @EmbeddedId
    private ClienteId id;

    //getters e setters e demais campos omitidos

}

Composite key of the customer

@Embeddable
public class ClienteId implements Serializable {

    @Column(name = "EMPRESA")
    private String empresa;
    @Column(name = "ID_CLIENTE")
    private String idCliente;

    //getters e setters omitidos
}

The problem is the mapping of the Client entity as a foreign key in the Order.

Entity Request with Customer

@Entity
@Table(name = "PEDIDOS")
public class PedidoEntity implements Serializable {

    @EmbeddedId
    private PedidoId id;

    @Column(name = "STATUS")
    private Integer status;

    @Column(name = "DATA_ENTREGA")
    private LocalDateTime dataEntrega;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumns(value = {
        @JoinColumn(name = "ID_CLIENTE", referencedColumnName = "ID_CLIENTE", updatable = false, insertable = false),
    @JoinColumn(name = "EMPRESA", referencedColumnName = "EMPRESA", updatable = false, insertable = false)})
    private ClienteEntity cliente;

}

As it stands, I am able to read the orders and bring the customer along through the call to pedidoRepository.findAll().

However, I cannot record a new order, passing along the existing customer in the requested entity and making a simple:

pedidoRepository.save(pedido);

Structure of the Order Table

EMPRESA    |  ID_PEDIDO   |    ID_CLIENTE   |   STATUS   |   DATA_ENTREGA

What is the correct way to map the Client (a composite foreign key) in the Order class?

1 answer

1


In your example you noted the relationship as follows:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumns(value = {
    @JoinColumn(name = "ID_CLIENTE", referencedColumnName = "ID_CLIENTE", updatable = false, insertable = false),
    @JoinColumn(name = "EMPRESA", referencedColumnName = "EMPRESA", updatable = false, insertable = false)
})
private ClienteEntity cliente;

Note that in the annotation @JoinColumn you filled the updatable and insertable properties as false.

In this case, when saving the Requested entity, it cannot insert these fields into the table because you specified that the entity manager should not write to them.

Remove this setting and leave it as follows:

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumns(value = {
    @JoinColumn(name = "ID_CLIENTE", referencedColumnName = "ID_CLIENTE"),
    @JoinColumn(name = "EMPRESA", referencedColumnName = "EMPRESA")
})
private ClienteEntity cliente;
  • I do not want to insert or update a customer through the order. I just want to save in the order the reference (relationship) to the customer. That’s not what those attributes say?

  • Note that the attributes, as much as they are on top of the client variable, concern the RELATIONSHIP with the client, so if you annotate with updatable false, for example, JPA will ignore this property in the update, not filling this field in the RELATIONSHIP. So it’s not about saving the client entity, it’s about filling the relationship.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.