2010-04-10 20 views
6

Q 1) ¿Cómo podemos modelar una relación ternaria usando Hibernate? Por ejemplo, ¿cómo podemos modelar la relación ternaria presentada here usando Hibernate (o JPA)?Relaciones ternarias (y n-arias) en Hibernate

NOTA: Sé que JPA 2 ha agregado algunas construcciones para construir relaciones ternarias usando mapas. Sin embargo, esta pregunta supone JPA 1 o Hibernate 3.3.x y no me gusta usar mapas para modelar esto.

ER Model http://db.grussell.org/co22001%20notes_files/image043.gif


ER Model with ternary relationships replaced http://db.grussell.org/co22001%20notes_files/image045.gif

Lo ideal sería que yo prefiero mi modelo a ser así:

class SaleAssistant { 
Long id; 
//... 
} 

class Customer { 
Long id; 
//... 
} 

class Product { 
Long id; 
//... 
} 

class Sale { 
SalesAssistant soldBy; 
Customer buyer; 
Product product; 
//... 
} 

Q 1.1)

¿Cómo podemos modelar esta variación, en el cual cada artículo de venta puede tener muchos productos?

class SaleAssistant { 
Long id; 
//... 
} 

class Customer { 
Long id; 
//... 
} 

class Product { 
Long id; 
//... 
} 

class Sale { 
SalesAssistant soldBy; 
Customer buyer; 
Set<Product> products; 
//... 
} 

Q 2) En general, ¿cómo podemos modelar n-aria, n> = 3 relaciones con Hibernate?

Gracias de antemano.

Respuesta

11

Q1. ¿Cómo podemos modelar una relación ternaria usando Hibernate? Por ejemplo, ¿cómo podemos modelar la relación ternaria presentada aquí usando Hibernate (o JPA)? (...)

Me gustaría remodelar la asociación con una clase de entidad intermedia (y esa es la manera recomendada con Hibernate). Aplicado a tu ejemplo:

@Entity 
public class Sale { 
    @Embeddable 
    public static class Pk implements Serializable { 
     @Column(nullable = false, updatable = false) 
     private Long soldById; 

     @Column(nullable = false, updatable = false) 
     private Long buyerId; 

     @Column(nullable = false, updatable = false) 
     private Long productId; 

     public Pk() {} 

     public Pk(Long soldById, Long buyerId, Long productId) { ... } 

     // getters, setters, equals, hashCode 
    } 

    @EmbeddedId 
    private Pk pk; 

    @ManyToOne 
    @JoinColumn(name = "SOLDBYID", insertable = false, updatable = false) 
    private SaleAssistant soldBy; 
    @ManyToOne 
    @JoinColumn(name = "BUYERID", insertable = false, updatable = false) 
    private Customer buyer; 
    @ManyToOne 
    @JoinColumn(name = "PRODUCTID", insertable = false, updatable = false) 
    private Product product; 

    // getters, setters, equals, hashCode 
} 

Q1.1. ¿Cómo podemos modelar esta variación, en la que cada artículo de venta podría tener muchos productos?

No utilizaría una clave primaria compuesta aquí e introduciría un PK para la entidad Sale.

Q2. En general, ¿cómo podemos modelar las relaciones n-ary, n> = 3 con Hibernate?

Creo que mi respuesta a Q1. cubre esto. Si no es así, por favor aclare.


Actualización: Contestación de los comentarios de la OP

(...) los campos del pk no se están pobladas y como consecuencia no puedo guardar elementos de venta en la base de datos. ¿Debería usar setters como este para la clase Sale? public void setBuyer (Customer cust) {this.buyer = cust; this.pk.buyerId = cust.getId(); }

Es necesario crear una nueva Pk (quité los constructores de mi respuesta original de la concisión) y configurarlo en el elemento Sale. Me gustaría hacer algo como esto:

Sale sale = new Sale(); 
Pk pk = new Pk(saleAssistant.getId(), customer.getId(), product.getId()); 
sale.setPk(pk); 
sale.setSoldBy(saleAssistant); 
sale.setBuyer(customer); 
sale.setProduct(product); 
... 

Y entonces se mantienen, el sale.

Además, en las anotaciones de JoinColumn, ¿a qué columna se refieren los campos de "nombre"? ¿Los pks de las relaciones objetivo o los propios nombres de columna de la tabla de ventas?

Para las columnas de los atributos de los Pk (es decir, propios nombres de las columnas de la tabla venta) compuestos, queremos que se obtienen PK y el FK limitaciones.

+0

Gracias por la respuesta. Pero me encuentro con un problema cuando uso esto: los campos del pk no se están llenando y, como resultado, no puedo guardar elementos de Venta en el DB. ¿Debo usar adaptadores como este para la clase Venta? public void setBuyer (Customer cust) { this.buyer = cust; this.pk.buyerId = cust.getId(); } Además, en las anotaciones de JoinColumn, ¿a qué columna se refieren los campos de "nombre"? ¿Los pks de las relaciones objetivo o los propios nombres de columna de la tabla de ventas? – Behrang

0

¿Está utilizando las claves principales generadas por la base de datos para clientes, productos y asistentes de ventas? Eso podría causar un problema ya que parece que está tratando de usar las identidades DB reales en lugar de dejar que Hibernate resuelva las referencias de los objetos durante la persistencia real.

El PK incrustado anterior parece extraño para mí personalmente, pero no he tenido la oportunidad de probarlo. Parece que las columnas se superponen y se golpean entre sí.

Creo que es suficiente con solo tener las referencias de ManyToOne.

Además, active la depuración de las sentencias de SQL y vea lo que se envía a la base de datos.