falha ao inicializar preguiçosamente uma coleção de papéis: com.pojo.Student.phonenos, nenhuma sessão ou sessão foi encerrada
-
27-10-2019 - |
Pergunta
Estou aprendendo o mapeamento de hibernação usando anotação. Concluí uma seção. Ou seja Posso inserir a classe filho automaticamente ao salvar a tabela pai. see_that .
Mas não obtive a tabela filho quando estou buscando a tabela mestre. Também obtendo um erro
failed to lazily initialize a collection of role: com.pojo.one2many.unidirectional.Student.phonenos, no session or session was closed
Meu código foi adicionado aqui para revisar você. Por favor, vá em frente. E me dê um ótimo conselho. Student.java. (aula de pais)
@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 filha)
@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;
}
minha 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;
}
A saída é
failed to lazily initialize a collection of role: com.pojo.one2many.unidirectional.Student.phonenos, no session or session was closed
Aqui estou usando mapeamento um-para-muitos unidirecional (chave estrangeira) (não tabela conjunta, bidirecional).
Summerizing minha pergunta
1) como obter a tabela filho quando buscamos a tabela pai, vice-versa
2) o que é busca ansiosa e preguiçosa.
3) mesa unidirecional, bidirecional e de junção no caso de mapeamento Um-para-Muitos, que tem mais potência total.
Solução
1)
Se você realmente deseja fazer isso toda vez que qualquer entidade dessas classes for recuperada, especifique FetchMode.EAGER
na associação @OneToMany
. @ManyToOne
são ansiosos por padrão. Esteja ciente de que isso pode ser bastante ineficiente se você precisar buscar essas entidades apenas em circunstâncias específicas. Se for esse o caso, você deve fazer como está fazendo, mas certifique-se de que a sessão que recuperou o objeto Student
ainda está aberta. Vendo que você está usando Spring, você tentou anotar seu DAO / Service com @Transactional
, para que a sessão se mantenha viva durante a execução do método? Ou você já tentou usar Hibernate.execute()
, como este:
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) Dê uma olhada nesta questão: Diferença entre FetchType LAZY e EAGER na persistência Java? .
3) Depende do que você precisa. Se você só precisa navegar na associação de uma maneira, defina-a unidirecional apenas dessa maneira. Se você precisar de ambos, faça os dois. O Join Table tem mais a ver com o design do banco de dados. Se você deseja ter um FK na tabela Phone
com a referência ao Student
ao qual o telefone pertence, ou deseja ter uma tabela de junção com o Phones
de cada Student
.