【问题标题】:Hibernate lazily loading fieldsHibernate 懒加载字段
【发布时间】:2014-08-07 03:28:34
【问题描述】:

我在休眠时遇到了这个问题。情况是我正在改造我的项目。我以前的项目是使用 JMS,它可以与我的 POJO 顺利运行。现在我正在尝试使用 Apache Mina(套接字编程)和 Google 的 Gson 重新创建它。

我的字段延迟加载有问题,因为使用 JMS 的项目在延迟加载时运行平稳,但现在我试图在数据库中检索一些值,但总是有一个休眠异常 g 指出 failed to lazily initialize a collection of role: class.field, no session or session was closed我想懒加载,我不想每次都检索它。

public class User {
    @Id
    @GeneratedValue
    @Column(name = "iduser")
    private Integer             iduser;

    @Column(name = "firstname")
    private String              firstname;

    @Column(name = "lastname")
    private String              lastname;

    //     this field causes the lazy loading exception
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    @BatchSize(size = 4)
    private Set<Transaction>    transaction;
}

我正在像这样在我的 DAO 中检索它

public User findByUser(String username, String pass) {
        // TODO Auto-generated method stub
        try {
            User instance = (User) getSession().createCriteria(User.class)
                    .add(Restrictions.eq(USERNAME, username))
                    .add(Restrictions.eq(PASS, pass)).uniqueResult();
            return instance;
        } catch (RuntimeException re) {
            throw re;
        }
    }

我调用服务的方法

public ModelAndView processSignin(User currentUser, BindingResult result,
            HttpServletRequest request) {
User user = service.signin(currentUser);
//i try to convert it to GSON but when i comment this line of code it works fine. but when gson tries to convert it to json string it seems that the annotations are being executed
System.out.println(gson.toJson(user));
}

调用DAO类的signin方法

public User signinDealer(User user) {
        // TODO Auto-generated method stub
        User currentUser = userDAO.signinUser(user);
        return currentUser;
    }

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    如果你使用 Spring 和 Hibernate(根据问题的标签似乎是这种情况),你可能要配置 Spring 事务管理(小教程:http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/)。

    然后,您必须使用 @Transactional 注释使用 Hibernate 实体的任何方法(在 Spring bean 上)。这将保证任何 Hibernate 对象都将在会话的上下文中加载,并且如果您碰巧触发了延迟初始化,Hibernate 将能够使用该会话获取对象。

    在您的情况下,您可能希望使用 @Transactional 注释将用户加载和序列化为 JSON 的方法。请注意,如果您有 2 个 Spring 应用程序上下文(一个根和一个用于 Spring MVC),注释很可能仅适用于根应用程序上下文中定义的 bean(因此注释控制器可能不起作用,请参阅@Transactional methods in @Controller class are not considred as transactional)。

    @Transactional
    public String signinAndSerialize(String username, String password) {
        User user = service.signin(username, password);
        return gson.toJson(user);
    }
    

    【讨论】:

    • @Transactional注解和使用AOP的事务管理有区别吗?
    • 不,这可能是一回事。 Spring 使用 AOP 来管理会话/事务。
    • 好吧,我已经在使用 AOP 事务管理,但它仍然会发生。我尝试了注释仍然是相同的输出
    • 不幸的是我已经这样做了。但似乎正在执行注释或正在执行转换过程中的getter。
    【解决方案2】:

    使用 Hibernate 时,延迟加载仅在加载整个对象的同一事务中调用字段的 getter 时才有效。这意味着,如果在事务完成时调用 getter,并且 Hibernate 会话关闭,则会引发延迟加载异常。

    您可以在事务块内进行转换,或者按照here 的说明从序列化中排除特定字段

    【讨论】:

      【解决方案3】:

      默认情况下,Hibernate 启用延迟加载。您可以执行以下操作:

      1. 首先评估您是否真的需要关系数据。如果您不需要关系数据,那么在 JSON 转换期间可以通过方法/注释忽略它。例如。使用 @JsonIgnore 注释该字段(import org.codehaus.jackson.annotate.JsonIgnore;)。

      2. 如果您确实需要数据,请在休眠会话仍处于打开状态时检索它。

      3. 通过将以下属性添加到您的 @OneToMany 注释 fetch=FetchType.EAGER 显式转换为 EagerLoading。但是,这会对性能产生影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-25
        • 2013-12-25
        • 1970-01-01
        • 1970-01-01
        • 2013-10-20
        相关资源
        最近更新 更多