首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在控制台应用程序中通过hibernate使用spring-data-jpa时延迟加载收集

如何在控制台应用程序中通过hibernate使用spring-data-jpa时延迟加载收集
EN

Stack Overflow用户
提问于 2013-02-18 22:37:07
回答 3查看 48.1K关注 0票数 31

我有一个小的控制台应用程序,我正在使用带有hibernate的spring-data-jpa。在一个独立的控制台应用程序中,当使用spring-data-jpa和它的存储库时,我真的不知道如何延迟初始化集合。下面是我的一些代码:

代码语言:javascript
复制
@Entity
public class User {
...
    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="USER_ORDER_ID")
    private Set<Order> orders = new HashSet<Order>();
...
}

存储库:

代码语言:javascript
复制
public interface UserRepository extends PagingAndSortingRepository<User, Long> {

    public ArrayList<User> findByFirstNameIgnoreCase(String firstName);
}

服务实施:

代码语言:javascript
复制
@Service
@Repository
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;

public ArrayList<User> findByFirstNameIgnoreCase(String firstName) {
    ArrayList<User> users = new ArrayList<User>();
    users = userRepository.findByFirstNameIgnoreCase(firstName);
    return users;
}

我的主要方法:

代码语言:javascript
复制
...
user = userRepository.findByFirstNameIgnoreCase("john").get(0);
orders = user.getOrders();
for (Order order : orders) {
  LOGGER.info("getting orders: " + order.getId());
}    

foreach循环得到一个异常:

org.hibernate.LazyInitializationException:延迟初始化role: com.aki.util.User.orders集合失败,未关闭任何会话或会话org.hibernate.LazyInitializationException:延迟初始化role集合失败:

请注意,当我使用某种类型的OpenSessionInViewFilter从when应用程序运行此程序时,不会出现此问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-18 22:58:19

一种解决方案是通过以下方式使User.orders成为一个急切获取的集合

代码语言:javascript
复制
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Order> orders = new HashSet<Order>();

默认情况下,实体关联是延迟加载的。这意味着orders集实际上只是一个代理对象,在您对其调用方法之前不会对其进行初始化。这很好,因为关联的Order对象只有在需要时才会加载。但是,如果您尝试在正在运行的事务之外访问未初始化的集合,则这可能会导致问题。

如果您知道在大多数情况下都需要用户的订单,那么就有必要急切地获取关联。否则,您必须确保在事务中初始化/加载集合。您提到的OpenSessionInViewFilter确保事务在请求处理期间保持打开状态,这就是为什么在yout webapp中不会出现此问题的原因。

如果您必须延迟加载它,请尝试使用Spring将代码包装在TransactionTemplate中:

代码语言:javascript
复制
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    protected void doInTransactionWithoutResult(TransactionStatus status) {
    ...
    }
});
票数 15
EN

Stack Overflow用户

发布于 2013-02-20 18:05:39

然而,我找到了一种方法。此方法位于我的服务实现中:

代码语言:javascript
复制
public Set<Order> fetchUserOrders(Long userId) {
    User user = userRepository.findOne(userId);
    Hibernate.initialize(user.getOrders());
    Set<Order> orders = user.getOrders();
    return orders;
}

注意:这是@zagyi在他的一条评论中建议的,但也要注意语句:Hibernate.initialize(user.getOrders());如果没有这个,集合仍然不会被初始化,你会得到一个错误。

票数 9
EN

Stack Overflow用户

发布于 2013-08-07 08:42:42

这对我很有效:

代码语言:javascript
复制
@Component
public class Test {

    @Inject 
    OrderDAO orderDAO;

    @PersistenceUnit
    private EntityManagerFactory emf;

    @PostConstruct
    public void test(){
        EntityManager em= emf.createEntityManager();
        for (Order o:orderDAO.findAll()){
            o=em.find(o.getClass(),o.getId());
            System.out.println(o.getLazyField());
        }
        em.close();
    }
}
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14938748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档