2012-01-23 18 views
19

devo classi utente e l'indirizzo come segue:Perché @OneToOne consente associazioni duplicate?

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

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

Ecco la mia ipotesi è con questo modello di dominio posso associare un indirizzo ad un solo utente (user.addr_id deve essere univoco).

Ma con questo modello di dominio, sono in grado di creare più utenti e associarli allo stesso indirizzo.

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

-> questo crea un record indirizzo con addr_id = 1 e inserendo un record utente in tabella utente con addr_id = 1. Belle.

Nuovamente,

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

-> Ciò crea disco secondo utente ed associando all'indirizzo esistente con addr_id = 1, che non è desiderato.

Posso usare @OneToOne (..) @ JoinColumn (name = "addr_id", unique = true) per impedire questo. Ma quale sarà la differenza nell'usare @OneToOne piuttosto che @ManyToOne (.., unique = true).

@OneToOne stesso dovrebbe imporre condizioni "univoco = vero" ... giusto?

-Siva

+0

Ho affrontato lo stesso problema. 'OneToOne' dovrebbe essere rinominato in' OneToOneOnEntityLevel'. Allo stesso modo 'JpaRepository.save()' dovrebbe essere 'jpaRepository.saveOrMerge()'. Queste due cose possono portare alla corruzione dei dati a livello di db. –

risposta

6

@OneToOne è annotare il Java per esprimere l'idea del rapporto tra le due classi. Se fosse un @OneToMany, avremmo invece una collezione. Quindi leggendo le annotazioni comprendiamo le realtionship e anche il runtime JPA comprende quelle.

L'effettiva sorveglianza del one-to-one viene eseguita nel database: abbiamo bisogno dello schema per avere i vincoli di unicità. @JoinColumn esprime il modo in cui tale relazione si manifesta nel DatabaseSchema.Questo può essere utile se stiamo generando lo schema.

Tuttavia in molti casi utilizziamo strumenti di tipo bottom-up per generare Java dallo schema. In questo caso non è necessario che le annotazioni Java riflettano i vincoli del database, da una prospettiva Java vediamo solo la relazione.

Un compilatore intelligente potrebbe avvertirci se la semantica della nostra @JoinColumn non corrisponde a @oneToOne, ma non sono sicuro che le attuali implementazioni lo facciano.

4

OneToOne è un'annotazione che descrive il modello dell'oggetto. Dice qual è la cardinalità dell'associazione. unique="true" è un'indicazione allo strumento "model-to-ddl" che dovrebbe esistere un cosntraint univoco in questa colonna. È possibile utilizzare tale strumento, ma si è anche liberi di creare e gestire autonomamente lo schema del database.

Qualsiasi cosa scegliate di fare, il motore JPA non effettua una query ogni volta che l'associazione OneToOne viene modificata per verificare che la cardinalità sia rispettata. Tutto ciò che fa è assumere che il codice sia corretto, e il vincolo univoco nel database farà in modo che la cardinalità sia rispettata.

Problemi correlati