Я пытаюсь получить поле сущности через скопированную сущность - PullRequest
0 голосов
/ 07 апреля 2019

У меня есть 2 сущности: певец и альбом.У певца есть несколько альбомов.Я скопировал суть певца и могу получить его имя и имя, но не могу получить список его альбомов.У меня есть это исключение

Исключение в потоке "main" org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию ролей: Entity.SingerEntity.albums, не удалось инициализировать прокси - нет Session

@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();
}

}

1 Ответ

1 голос
/ 07 апреля 2019

Прежде всего правильно сопоставьте двунаправленное отношение 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...