繁体   English   中英

春季懒惰加载一对多

[英]Lazy loading one to many in spring

我陷在这个问题上。 基本上,我在实体UserBook之间有一对多关系(User可以有很多书),两个事务存储库和事务服务。 我在休眠实现中使用JPA。

当我尝试访问延迟加载的书籍列表时,出现NullPointerException并且在启用SQL日志时,我注意到未调用sql查询。 如果我改变渴望,它会按预期工作。

这是我认为与该问题有关的代码:

User.java

@Entity
public class User {
...
   @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch =        FetchType.LAZY)
   @JsonIgnore
   private List<Book> rentedBooks;

Book.java

@Entity
public class Book {
...
    @ManyToOne(optional = true)
    @JoinColumn(name = "user_ID")
    @JsonProperty("user")
    private User user;

BookRepository.java

@Repository
@Transactional(Transactional.TxType.MANDATORY)
public class BookRepository {
    @PersistenceContext
    public EntityManager em;

UserRepository.java

@Repository
@Transactional(Transactional.TxType.MANDATORY)
public class UserRepository {
    @PersistenceContext
    EntityManager em;

BookService.java

@Service
@Transactional(Transactional.TxType.REQUIRED)
public class BookServices {
...
public void rentBook(String bookID, String fbID) {
        if (!userRepository.checkIfUserExists(fbID)) {
            User user = new User(fbID);
            userRepository.addUser(user);
        }
        User user = userRepository.findByUserByFacebookID(fbID);
        Book book = bookRepository.findBookByGoogleBookID(bookID);

        book.setStatus(Status.rented);
        book.setUser(user);
        bookRepository.updateBook(book);

        //user.getRentedBooks() is null
        user.getRentedBooks().add(book);
    }

我注意到,如果用户不存在并创建,则getRentedBooks为null,但是如果它是较早创建的,则getRentedBooks不为null,并且可以像预期的那样进行延迟加载。

这是我的配置:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.polarcape" />
    <!--<property name = "hibernate.show_sql" value = "true" />-->
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

UserService初始化User对象的List<Book>

User user = userRepository.findByUserByFacebookID(fbID);
Hibernate.initialize(user.getRentedBooks()); //Initialize the lazy-loaded collection
Book book = bookRepository.findBookByGoogleBookID(bookID);

关于Hibernate.initialize()需求的快速介绍:(来自此处的文档)

如果在Session范围之外访问未初始化的集合或代理,即当拥有该集合或对该代理的引用的实体处于分离状态时,Hibernate将抛出LazyInitializationException。

在您的情况下, List<Book>是未初始化的集合

在常见情况下,将联名book与其user一起user您必须清除更改。 然后,您只需要刷新 user实例。

在您的情况下,您也可以这样做,但是通过编程更正确地保持对象模型的一致性,您应该将book添加到user.rentedBooks集合中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM