1

I have this issue with hibernate. the scenario is that i'am remaking my project. my previous project is with JMS which runs smoothly with my POJOs. and now i am trying to recreate it using Apache Mina(socket programming) with Google's Gson.

I am having problem with lazy loading of my fields, because the project that uses JMS runs smooth with lazy loading but now i am trying to retrieve some value in the database but there is always a hibernate exceptiong stating that failed to lazily initialize a collection of role: class.field, no session or session was closed which i want to load lazily, i dont want to retrieve it everytime.

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;
}

and i am retrieving it in my DAO like this

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;
        }
    }

the method where i call the service

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));
}

signin method that calls the DAO class

public User signinDealer(User user) {
        // TODO Auto-generated method stub
        User currentUser = userDAO.signinUser(user);
        return currentUser;
    }
Ker p pag
  • 1,568
  • 12
  • 25

3 Answers3

0

If you use Spring and Hibernate (which seems the case according to the tags of the question), you may want to configure Spring transaction management (small tutorial: http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/).

Then, you'll have to annotate any method (on a Spring bean) that uses a Hibernate entity with @Transactional. This will guarantee that any Hibernate object will be loaded in the context of a session, and that if you happen to trigger a lazy initialization, Hibernate will be able to fetch the objects using that session.

In your case you may want to have the method that both loads and serializes the User to JSON be annotated with @Transactional. Note that if you have 2 Spring application contexts (one root and one for Spring MVC), the annotation will most likely only work on beans defined in the root application context (so annotating the controller might not work, see @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);
}
Community
  • 1
  • 1
Christophe L
  • 13,725
  • 6
  • 33
  • 33
  • is @Transactional annotation different from transaction management using AOP? – Ker p pag Aug 07 '14 at 03:41
  • No that's probably the same thing. Spring uses AOP to manage the session / transaction. – Christophe L Aug 07 '14 at 03:44
  • well i am already using AOP transaction management, still it occurs. and i tried the annotation still the same output – Ker p pag Aug 07 '14 at 03:45
  • unfortunately i already did that. but it seems that the annotations are being executed or the getters are getting executed in the process of conversion. – Ker p pag Aug 07 '14 at 04:02
0

When working with Hibernate, the lazy loading only works when the getter of the field is invoked inside the same transaction that loads the entire object. That means, if the getter is invoked when the transaction has finished, and the Hibernate session closed, the lazy loading exception is thrown.

You can make the conversion inside the transaction block, or exclude the specific field from serialization as explained here

Community
  • 1
  • 1
guanguer
  • 56
  • 1
0

By default Hibernate enables lazy loading. You could do following:

  1. First evaluate whether you really need the relationship data. If you don't need the relationship data then there are ways / annotations to ignore it during JSON conversion. For eg. annotating the field with @JsonIgnore (import org.codehaus.jackson.annotate.JsonIgnore;).

  2. If you really need the data then retrieve it while your hibernate session is still open.

  3. Explicitly convert to EagerLoading by adding following attribute to your @OneToMany annotation fetch=FetchType.EAGER. However, this will have a performance impact.

Vikram Rawat
  • 1,472
  • 11
  • 16