我有2个实体:一个歌手和一个专辑。歌手有几张专辑。我复制了歌手的本质,可以获取他的ID和姓名,但无法获取他的专辑清单。 我有这个秘诀
线程“ main” org.hibernate.LazyInitializationException中的异常:无法延迟初始化角色集合:Entity.SingerEntity.albums,无法初始化代理-没有会话
@Entity
@Table(name = "\"singer\"")
public class SingerEntity {
@Id
private int singer_id;
private String name;
@OneToMany(mappedBy = "singer_id", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AlbumEntity> albums;
public List<AlbumEntity> getAlbums() {
return albums;
}
public void setAlbums(List<AlbumEntity> albums) {
this.albums = albums;
}
@Entity
@Table(name = "album")
public class AlbumEntity {
@Id
private int album_id;
private String album_title;
private String genre;
private int singer_id;
主要方法:
public static void main(String[] args) {
SingerDAO sDAO = new SingerDAO();
AlbumDAO aDAO = new AlbumDAO();
SingerEntity s1 = new SingerEntity(1, "Singer");
sDAO.insert(s1);
AlbumEntity a1 = new AlbumEntity(1, "a1", "g1", s1);
AlbumEntity a2 = new AlbumEntity(2, "a2", "g1", s1);
AlbumEntity a3 = new AlbumEntity(3, "a3", "g2", s1);
AlbumEntity a4 = new AlbumEntity(4, "a4", "g2", s1);
aDAO.insert(a1);
aDAO.insert(a2);
aDAO.insert(a3);
aDAO.insert(a4);
s1 = sDAO.findById(1);
System.out.println(s1.getId() + " , " + s1.getName());
List<AlbumEntity> albums = s1.getAlbums();
System.out.println(albums.get(0).getAlbum_title());
}
SingerDAO类:
public class SingerDAO {
public SingerEntity findById(int id) {
Session session = null;
SingerEntity singer = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
singer = (SingerEntity) session.get(SingerEntity.class, id);
Hibernate.initialize(singer);
} catch (Exception e){
e.printStackTrace();
} finally {
if (session != null && session.isOpen()){
session.close();
}
}
return singer;
}
public void select(){
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Query query= session.createQuery("from SingerEntity");
List<SingerEntity> list = query.list();
for (SingerEntity s:list) {
System.out.println(s.getName());
}
session.getTransaction().commit();
session.close();
}
public void insert(SingerEntity singerEntity){
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.save(singerEntity);
session.getTransaction().commit();
session.close();
}
public void update(SingerEntity sE){
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.update(sE);
session.getTransaction().commit();
session.close();
}
public void delete(SingerEntity sE){
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.delete(sE);
session.getTransaction().commit();
session.close();
}
}
答案 0 :(得分:1)
首先正确映射OneToMany双向关系。你应该有
@Entity
@Table(name = "singer")
public class SingerEntity {
...
@OneToMany(mappedBy = "singer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AlbumEntity> albums;
...
}
@Entity
@Table(name = "album")
public class AlbumEntity {
...
@ManyToOne
@JoinColumn(name = "singer_id)
private SingerEntity singer;
....
}
如果您想更好地将专辑添加到实体,请使用Singer实体上的自定义方法来保持引用正确,如:
public void addAlbum(AlbumEntity a) {
albums.add(a);
a.setSinger(this);
}
之后,您可以保存专辑,只要拥有Cascade选项就可以保留歌手。
然后,默认情况下,由于OneToMany关系集合是惰性的,您应该将其加载到获得SingerEntity的同一事务中。因此,SingerEntity将附加到Hibernate会话。例如,您可以在方法上使用Spring @Transactional批注。
我看不到您的DAO代码,但main可以看到:
SingerDAO sDAO = new SingerDAO();
AlbumDAO aDAO = new AlbumDAO();
SingerEntity s1 = new SingerEntity(1,"Singer");
s1.addAlbum(new AlbumEntity(1,"a1","g1",1));
s1.addAlbum(new AlbumEntity(2,"a2","g2",1));
s1.addAlbum(new AlbumEntity(3,"a3","g3",1));
s1.addAlbum(new AlbumEntity(4,"a4","g4",1));
sDAO.insert(s1);
更改findById以使用一个事务进行延迟加载:
public SingerEntity findById(int id) {
Session session = null;
SingerEntity singer = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
//start transaction
singer = (SingerEntity) session.get(SingerEntity.class, id);
Hibernate.initialize(singer);
//end transaction
} catch (Exception e){
e.printStackTrace();
} finally {
if (session != null && session.isOpen()){
session.close();
}
}
return singer;
}