2012-01-23 17 views
19

que tienen clases de usuario y la dirección de la siguiente manera:¿Por qué @OneToOne está permitiendo asociaciones duplicadas?

class User 
{ 
    ... 
    ... 
    @OneToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="addr_id") 
    private Address address; 
} 

class Address 
{ 
    ... 
    ... 
    @OneToOne(mappedBy="address") 
    private User user; 
} 

Aquí mi suposición es con este modelo de dominio puedo asociar una dirección a un solo usuario (user.addr_id debe ser único).

Pero con este modelo de dominio, puedo crear varios usuarios y asociarlos a la misma dirección.

User u1 = new User(); 
//set data 
Address addr1 = new Address(); 
//set data 
u1.setAddress(addr1); 
... 
session.save(u1); 

-> esto está creando un registro de direcciones con addr_id = 1 y la inserción de registro de un usuario en la tabla de usuario con addr_id = 1. Multa.

Una vez más,

User u2 = new User(); 
//set data 
Address addr1 = (Address) session.load(Address.class, 1); 
//set data 
u2.setAddress(addr1); 
... 
session.save(u2); 

-> Esto está creando segundo registro de usuario y asociar a la dirección existente con addr_id = 1, que no se desea.

Puedo usar @OneToOne (..) @ JoinColumn (name = "addr_id", unique = true) para evitar esto. Pero cuál será la diferencia de usar @OneToOne en lugar de @ManyToOne (.., unique = true).

@OneToOne en sí debería imponer la condición "único = verdadero" ... ¿correcto?

-Siva

+0

Me enfrenté al mismo problema. 'OneToOne' debe ser renombrado a' OneToOneOnEntityLevel'. Del mismo modo 'JpaRepository.save()' debe ser 'jpaRepository.saveOrMerge()'. Estas dos cosas pueden conducir a la corrupción de datos a nivel de base de datos. –

Respuesta

6

@OneToOne está anotando el Java para expresar la idea de la relación entre las dos clases. Si esto fuera un @OneToMany, tendríamos una colección en su lugar. Entonces, al leer las anotaciones comprendemos las relaciones reales, y el tiempo de ejecución de JPA también las comprende.

La vigilancia real del uno-a-uno se realiza en la base de datos; necesitamos que el esquema tenga las restricciones de exclusividad. El @JoinColumn expresa cómo esa relación se manifiesta en DatabaseSchema. Esto puede ser útil si estamos generando el esquema.

Sin embargo, en muchos casos, utilizamos herramientas ascendentes para generar Java a partir del esquema. En este caso, no existe una necesidad real de que las anotaciones Java reflejen las restricciones de la base de datos, desde una perspectiva Java, simplemente vemos la relación.

Un compilador inteligente podría advertirnos si la semántica de nuestro @JoinColumn no coincide con @oneToOne, pero no estoy seguro de si las implementaciones actuales lo hacen.

4

OneToOne es una anotación que describe el modelo de objetos. Dice cuál es la cardinalidad de la asociación. unique="true" es una indicación para la herramienta "model-to-ddl" de que debe haber una restricción única en esta columna. Puede utilizar dicha herramienta, pero también puede crear y mantener el esquema de la base de datos usted mismo.

Independientemente de lo que elija hacer, el motor JPA no realiza una consulta cada vez que se modifica la asociación de OneToOne para verificar que se respete la cardinalidad. Todo lo que hace es suponer que el código es correcto, y la restricción única en la base de datos se asegurará de que se respete la cardinalidad.

Cuestiones relacionadas