简体   繁体   English

使用带有fetch = FetchType.LAZY的休眠状态从表中获取数据

[英]Fetch data from table using hibernate with fetch=FetchType.LAZY

I'm trying to get all user's emails from table. 我正在尝试从表中获取所有用户的电子邮件。 Entity user: 实体用户:

     @Entity
     @Table(name = "tbl_User")
     public class User {
          @Expose
          @Id
          @GeneratedValue
          @Column(name = "id")
          private Long id;
          .....
          @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
          List<CommunicationAddress> communicationAddresses = new ArrayList<CommunicationAddress>();
          .....
     } 

In the service I'm getting user and trying to look emails: 在服务中,我正在吸引用户并尝试查看电子邮件:

User user = userDAO.getUserById(id);
        if (user == null) {
            throw new Exception("User not found");
        } else {
            List<Email> addresses = user.getCommunicationAddresses();
        }

But I received the next exception: 但是我收到了下一个例外:

 org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
        at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:137)
        at org.hibernate.collection.internal.PersistentBag.isEmpty(PersistentBag.java:249)

The method for getting user: 获取用户的方法:

@Transactional
@Override
public User getUserById(Long userId) {
    Criteria criteria = sessionFactory.getCurrentSession().createCriteria(User.class);
    criteria.add(Restrictions.eq("id", userId));
    return (User) criteria.uniqueResult();
}

I understand that I must to get communicationAddresses when I get User using Criteria... How to do it? 我了解使用条件获取用户时必须获取通讯地址。 Thank's all. 谢谢大家

It seems your service method is not annotated with @Transactional . 看来您的服务方法未使用@Transactional注释。 Thus, after calling userDAO.getUserById(id); 因此,在调用userDAO.getUserById(id); , there is no longer a transaction. ,不再有交易。 That means that you cannot access any lazy-loaded properties of the loaded entity that hasn't been accessed/pre-fetched inside the transaction without running into a LazyInitializationException. 这意味着您不能访问未在事务内部访问/未预取的已加载实体的任何延迟加载属性,而不会遇到LazyInitializationException。
So you can either think about replacing LAZY with EAGER fetching (this mostly depends on the use cases you are facing) or you should annotate your Service method with @Transactional . 因此,您可以考虑用EAGER抓取替换LAZY (这主要取决于您面临的用例),或者应该使用@Transactional注释Service方法。

I'd highly suggest to annotate your service methods (instead of the DAO methods), as only there you can establish meaningful transactional boundaries when interacting with multiple entities. 我强烈建议注释您的服务方法(而不是DAO方法),因为只有这样您才能与多个实体交互时建立有意义的事务边界。
Also, if you make usage of lazy loading, you must be aware of the possibility to run into that kind of exception after leaving the service layer, eg when rendering your view (assuming you somehow present the data). 另外,如果您使用延迟加载,则必须注意离开服务层后可能会发生这种异常的可能性,例如在渲染视图时(假设您以某种方式呈现数据)。

"Prefetching' lazy associations “预取”懒惰的关联

To trigger instant loading of lazy associations (called " dynamic association fetching "), add this line in getUserById : 要触发即时加载惰性关联(称为“ 动态关联获取 ”),请在getUserById添加以下行:

criteria.setFetchMode("communicationAddresses", FetchMoode.EAGER);

However, if you do that in this specific method, I wonder why you stick to lazy loading at all? 但是,如果您以这种特定方法进行操作,我想知道为什么您仍然坚持延迟加载吗?

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

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