impossibile inizializzare pigramente una raccolta di ruoli: com.pojo.Student.phonenos, nessuna sessione o sessione è stata chiusa
-
27-10-2019 - |
Domanda
Sto imparando la mappatura ibernata utilizzando l'annotazione. Ho completato una sezione. Cioè Posso inserire automaticamente la classe figlio quando salvo la tabella genitore. see_that .
Ma non ho ricevuto la tabella figlia durante il recupero della tabella principale. Ricevo anche un errore
failed to lazily initialize a collection of role: com.pojo.one2many.unidirectional.Student.phonenos, no session or session was closed
Il mio codice viene aggiunto qui per esaminarti. Per favore, esaminalo. E dammi l'ottimo consiglio. Student.java. (classe genitore)
@Entity
@Table(name="STUDENT")
public class Student {
private int studentid;
private String studentName;
private Set <Phone> phonenos;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="studenId")
public int getStudentid() {
return studentid;
}
public void setStudentid(int studentid) {
this.studentid = studentid;
}
@Column(name="studenName")
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="studenId")
public Set<Phone> getPhonenos() {
return phonenos;
}
public void setPhonenos(Set<Phone> phonenos) {
this.phonenos = phonenos;
}
Phone.java (classe figlio)
@Entity
@Table(name = "PHONE")
public class Phone {
private int phoneid;
private String phoneNo;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "phoneId")
public int getPhoneid() {
return phoneid;
}
public void setPhoneid(int phoneid) {
this.phoneid = phoneid;
}
@Column(name = "phoneno")
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
la mia classe dao
public List<Student> getAllStudent() {
List<Student> studentList = null;
try {
DetachedCriteria criteria = DetachedCriteria.forClass(Student.class);
studentList = (List<Student>)getHibernateTemplate().findByCriteria(criteria);
if(studentList != null && ! studentList.isEmpty()){
for(Student st :studentList){
System.out.println(" st name : "+st.getStudentName());
if(st.getPhonenos() != null && ! st.getPhonenos().isEmpty()){
for(Phone ph : st.getPhonenos()){
System.out.println(" ph no : "+ ph.getPhoneNo());
}
}else{
System.out.println(" phone number is null");
}
}
}else{
System.out.println(" student null");
}
} catch (DataAccessException e) {
e.printStackTrace();
}
return studentList;
}
L'out put è
failed to lazily initialize a collection of role: com.pojo.one2many.unidirectional.Student.phonenos, no session or session was closed
Qui sto usando la mappatura uno-a-molti unidirezionale (chiave esterna) (non tabella congiunta, bidirezionale).
Riassumendo la mia domanda
1) come ottenere la tabella figlia quando recuperiamo la tabella genitore, viceversa
2) ciò che è desideroso e pigro.
3) tabella unidirezionale, bidirezionale e di unione nel caso di mappatura uno-a-molti quale è più potente.
Soluzione
1)
Se vuoi davvero farlo ogni volta che viene recuperata una qualsiasi entità di queste classi, specifica FetchMode.EAGER
nell'associazione @OneToMany
. @ManyToOne
sono desiderosi per impostazione predefinita. Tieni presente che ciò potrebbe essere in gran parte inefficiente se devi recuperare quelle entità solo in circostanze particolari. Se è così, devi farlo come stai facendo, ma assicurati che la sessione che ha recuperato l'oggetto Student
sia ancora aperta. Visto che stai usando Spring, hai provato ad annotare il tuo DAO / Servizio con @Transactional
, in modo che la sessione rimanga viva durante l'esecuzione del metodo? Oppure hai provato a utilizzare Hibernate.execute()
, in questo modo:
getHibernateTemplate().execute(new HibernateCallback(){
@SuppressWarnings("unchecked")
public Object doInHibernate(Session s) throws HibernateException, SQLException {
Criteria c = s.createCriteria(Student.class);
List<Student> studentList = c.list();
for(Student st :studentList){
st.getPhoneNos();
}
}
});
2) Dai un'occhiata a questa domanda: Differenza tra FetchType LAZY e EAGER nella persistenza Java? .
3) Dipende da cosa ti serve. Se è necessario navigare l'associazione in un solo modo, definirla unidirezionale solo in quel modo. Se hai bisogno di entrambi, fallo entrambi. Join Table ha più a che fare con la progettazione del database. Se vuoi avere un FK nella tabella Phone
con il riferimento al Student
a cui appartiene il telefono, o vuoi avere una tabella join con il Phones
di ogni Student
.