Pergunta

I currently have a structure as follows (pseudocode):

public class Order
{
    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;

    private Client client;
}

public class Orderline
{
    @ManyToOne(mappedBy = 'orderlines')
    private Order order;

    private Client client;
}

public class Client
{
    // your usual Client class, its contents aren't important for the question
}

Say that I can have an order with ID 123, which belongs to client X. I can also have an order with ID 123 which belongs to client Y. When lazy loading (or eager loading, for that matter), how can I know that when I fetch order with ID 123 for client X from the database, I won't be getting the orderlines from client Y? If JPA checks on the foreign key on the orderline side only, is there a way to add a check for the client when lazy (or eager) loading?

I would like to solve this without using specific implementations like Hibernate or Eclipselink so I can easily switch between implementations if necessary.

Foi útil?

Solução

Your choice of ID is probably not sufficient if you are just using the "ID (123)" as the ID of the Order entity.

In JPA, each entity should have a unique identifier. If there are going to be two Orders (one for X and one for Y) using the same ID, then everything is messed up.

My personal recommendation is to make ID unique across the whole system. If you want some kind of sequence number per client, keep it as another field.

Of course, there is another choice of making Client ID and Order ID as a composite key.

In short, make sure your choice of ID can uniquely identify an entity (usually means, a row in DB).

An example (First approach, unique ID)

public class Order
{
    @Id
    private Long id;

    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;

    private Client client;

    private Long orderSequence;  // unique within a client
}

public class Orderline
{
    @Id
    private Long id;   // unique ID of order line

    @ManyToOne(mappedBy = 'orderlines')
    private Order order;

    // not necessary, as you can access through orderLine.order.client
    // private Client client;
}

Second approach (Composite key):

public class Order
{
    @EmbeddedId
    private OrderId id;

    @ManyToOne
    @JoinColumn(insertable=false, updatable=false)
    private Client client;

    @Column(insertable=false, updatable=false)
    private Long orderSequence;  // unique within a client

    @OneToMany(targetEntity = Orderline.class, fetch = FetchType.LAZY)
    private List<Orderline> orderlines;
}

@Embeddable
public class OrderId {
    Long clientId;
    Long orderSequence;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top