2015-05-11 23 views
7

Ho meno di 1-m relazione su entità che Mentore agli studenti. Il tutore svolge chiave primaria composita che io uso come chiave esterna studentePersistono entità 1-m con chiave primaria composita in ibernazione

@Entity 
public class Mentor implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    private MentorPK id; 
    private String email; 
    @OneToMany(mappedBy="mentor") 
    private Set<Student> students; 

    public MentorPK getId() { 
     return id; 
    }    
    //getters and setters 
} 

@Embeddable 
public class MentorPK implements Serializable { 

    private static final long serialVersionUID = 1L; 
    private String name; 
    private String add; 
    //getters and setters 
    //override equals and hashcode 
} 


@Entity 
public class Student implements Serializable{ 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private int id; 
    private String name;  

    @ManyToOne 
    @MapsId("id") 
    @JoinColumns({ 
     @JoinColumn(name="name_fk", referencedColumnName="name"), 
     @JoinColumn(name="address_fk", referencedColumnName="address") 
    }) 
    private Mentor mentor; 

    //Getters and setters 
} 

ho ancora insistere sopra come sotto ma solo la Mentor è persistito dove studente tavolo è vuota.

Come posso mantenere il mentore con gli studenti?

Set<Student> students = new HashSet<Student>(); 

Student s1 = new Student(); 
s1.setName("Student 1"); 

Student s2 = new Student(); 
s2.setName("Student 2"); 

students.add(s1); 
students.add(s2); 

MentorPK mpk = new MentorPK(); 
mpk.setAddress("C"); 
mpk.setName("D"); 

Mentor m = new Mentor(); 
m.setId(mpk); 
m.setEmail("emaill"); 
m.setStudents(students); 

studentManager.saveMentor(m); 
+0

Forse questo è in realtà un problema con la generazione automatica della chiave primaria dell'ID dello studente. Puoi creare studenti senza mentori? – DuncanKinnear

+0

@DuncanKinnear yes i can – Harshana

risposta

2

Prova a cambiare l'annotazione di campo agli studenti di

@OneToMany(mappedBy="mentor", cascade = CascadeType.PERSIST)

+0

non ha funzionato aggiungendo l'attributo cascade = CascadeType.PERSIST – Harshana

+0

Ho appena creato un piccolo progetto di esempio utilizzando il codice che hai fornito (correzione dell'indirizzo/aggiunta incoerenza del nome campo e rimozione dell'annotazione @MapsId obsoleta) e aggiunta della cascata digita e ha funzionato come previsto, dopo aver chiamato entityManager.persist (m) anche gli studenti sono rimasti persi. –

+0

Ho appena notato che menzioni l'ibernazione, ho creato l'esempio usando eclipselink. Potresti provare a utilizzare l'ultima versione e se ancora non funziona, controlla se si tratta di un bug segnalato o segnalalo come bug. –

2

Quando si utilizza un composito-chiave, mappata come Embeddable è necessario utilizzare @EmbeddedId:

@Entity 
public class Mentor { 

    @EmbeddedId 
    private MentorPK id; 

    private String email; 
    @OneToMany(mappedBy="mentor") 
    private Set<Student> students; 

    public MentorPK getId() { 
     return id; 
    }    
    //getters and setters 
} 

e la Lo studente diventa:

@Entity 
public class Student { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private int id; 
    private String name;  

    @ManyToOne 
    @JoinColumns({ 
     @JoinColumn(name="name_fk", referencedColumnName="name"), 
     @JoinColumn(name="address_fk", referencedColumnName="address") 
    }) 
    private Mentor mentor; 

    //Getters and setters 
} 

Il @MapsId viene utilizzato quando sia lo @Id che lo @ManyToOne condividono le stesse colonne del database, che non è il tuo caso, poiché hai un identificatore numerico e una chiave esterna composita.

1

Come di cambiare:

@OneToMany(mappedBy="mentor") 
private Set<Student> students; 

a:

@OneToMany(mappedBy="mentor") 
private Set<Student> students = new HashSet(); 

o

@OneToMany(cascade=CascadeType.ALL) 
@JoinColumn(name="student_id") 
@org.hibernate.annotations.IndexColumn(name="idx") 
private Set<Student> students = new HashSet(); 

anche cercare di non saltare

= new HashSet(); 

parte

2

Potrebbe essere necessario creare il riferimento da studente a mentore in ogni studente.

Quindi, nel codice, dopo aver creato m è necessario:

s1.setMentor(m); 
s2.setMentor(m); 

Altrimenti Hibernate non può sapere che cosa per popolare le colonne name_fk e address_fk con.

+0

non ha funzionato così anche. Credo di dover insistere prima sullo studente e poi perseverare con gli studenti – Harshana

1

Come ho capito la richiesta, vorresti che il mentore fosse il proprietario del rapporto. Non ottieni questo con la riga @OneToMany(mappedBy="mentor"). Questo in effetti mette lo studente come il proprietario della relazione.

Ho testato questo modello di dominio e ho apportato alcune modifiche alle annotazioni per fare in modo che il codice di test funzioni come previsto.

Student

public class Student implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy= GenerationType.AUTO) 
    private int id; 
    private String name; 

    @ManyToOne 
    @JoinColumns({ 
      @JoinColumn(name="name_fk", referencedColumnName="name", insertable = false, updatable = false), 
      @JoinColumn(name="address_fk", referencedColumnName="address", insertable = false, updatable = false) 
    }) 
    private Mentor mentor; 

//setters and getters 
} 

Mentor

public class Mentor implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    private MentorPK id; 
    private String email; 
    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumns({ 
      @JoinColumn(name="name_fk", referencedColumnName="name"), 
      @JoinColumn(name="address_fk", referencedColumnName="address") 
    }) 
    private Set<Student> students; 
//setters and getters 
} 

Funziona anche senza fare: s1.setMentor(m);s2.setMentor(m);. Non me l'aspettavo, ma sembra che l'ibernazione abbia a che fare con questo.

Un articolo correlato è here.

Attenzione: rilasciare le tabelle del database dopo aver modificato le annotazioni per consentire a Hibernate di ricreare le tabelle.

+0

Grazie. Ma in realtà voglio che lo studente sia il proprietario della relazione. Questo è il motivo per cui ho messo mappedBy nel lato Mentor. Quindi penso che il modello sia corretto ma il modo in cui persisto i dati nel client è sbagliato. Puoi rispondere come mantenere lo studente con il mentore in modo corretto – Harshana

+0

Provo di seguito, Student s1 = new Student(); s1.setName ("Studente 1"); \t \t MentorPK mpk = new MentorPK(); mpk.setAddress ("C"); mpk.setName ("D"); Mentore m = nuovo Mentore(); m.setId (mpk); m.setEmail ("emaill"); \t \t s1.setMentor (m); //studentManager.saveMentor(m); studentManager.saveStudent (s1); Ma mi ha dato "EntityNotFoundException: Impossibile trovare com.ejb.entities.Mentor con id [email protected]". Quindi continuo il mentore prima di salvare lo studente. Quindi non posso inserire NULL in ("SYS". "STUDENT". "ADDRESS_FK") eccezione – Harshana