23
Окт
2015

JpaRepository + Hibernate + OneToMany вылетает LazyInitializationException

реализую отношение one-to-many по этому туториалу а также этому спринговому туториалу. Я НЕ использую сессии и прочий hibernate напрямую, я использую JpaRepository и аннотации JPA. Есть объекты Owner (one) & Book (many):

первая таблица:

@Entity
@Table(name = "owners")
public class Owner implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "owner_id", nullable = false, unique = true)
    private Long id;

    @Column(name = "owner_name", nullable = false)
    private String name;

    @OneToMany(fetch = FetchType.LAZY,mappedBy = "owner")
    private Set<Book> books= new HashSet<>(0);

    public Worker() {
    }
}

вторая таблица:

@Entity
@Table(name = "books")
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_id", unique = true, nullable = false)
    private Long id;

    @Column(name = "book_name", nullable = false, unique = true)
    private String name;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "owner_id")
    private Owner owner;

    public Task() {
    }
}

слой репозиториев стандартный, без реализации:

public  interface OwnerRepository extends JpaRepository<Owner,Long> {}

public  interface BookRepository extends JpaRepository<Book,Long> {}

Owner service: (book service такой же)

@Service
@Transactional
public class OwnerServiceImpl implements OwnerService {

    @Autowired
    private OwnerRepository ownerRepository;

    @Override
    public Owner create(Owner owner) {return ownerRepository.save(owner);}

    @Override
    public Owner read(Long id) {return ownerRepository.findOne(id);}

    @Override
    public List<Owner> readAll() {return ownerRepository.findAll();}

    @Override
    public void delete(Owner owner) {ownerRepository.delete(owner);}

}

Создав два класса service, я захотел протестить их. Создал несколько Owner,Book ну и пытаюсь связать их как указано здесь, т.е. добавляю в объектe Owner в Set новую книжку, а в объект Book обновляю ссылку на Owner. Сохраняю в репозиторий сначала Owner, затем Book. Затем пытаюсь прочитать Owner из репозитория, а во время обращения к полю выдаёт

unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.

может я вообще неправильно работаю с репозиторием и JPA? как нужно сохранять/обновлять ссылки в сущностях?

===UPDATE===

мне кажется я решил проблему, использовав @NamedEntityGraph & @EntityGraph. Я аннотировал Owner

@NamedEntityGraph(name = "Owner.books",
    attributeNodes = @NamedAttributeNode("books"))

Но в интерфейсе репозитория пришлось переопределить стандартные методы:

@Override
@EntityGraph(value = "Owner.books", type = EntityGraph.EntityGraphType.LOAD)
List<Owner> findAll();


@Override
@EntityGraph(value = "Owner.books", type = EntityGraph.EntityGraphType.LOAD)
OwnerfindOne(Long aLong);

Тоже самое сделал с Book. Когда я делаю запрос из репозитория Owner на считывание объекта, всё загружается нормально - ссылки в Set ссылаются на объекты Book. Но когда я делаю запрос к Book репозиторию - объект Book имеет ссылку на Owner, НО в этом внутреннем Owner ссылки на дополнительные книги бросают LazyInitException. Почему? ссылки просматриваю в Idea на брек поинте.

Источник: https://ru.stackoverflow.com/questions/460585/jparepository-hibernate-onetomany-%D0%B2%D1%8B%D0%BB%D0%B5%D1%82%D0%B0%D0%B5%D1%82-lazyinitializationexception

Тебе может это понравится...

Добавить комментарий