1

I am currently using Hibernate 4.3.5 in Spring MVC 4.2.3. I have two model User and Client, where id of User is the foreign key of Client.

In the User class:

@Repository
@Transactional
public class UserDAOImpl implements UserDAO {

@Autowired
private SessionFactory sessionFactory;

protected SessionFactory getSessionFactory() {
    try {
        return (SessionFactory) new InitialContext().lookup("SessionFactory");
    } catch (Exception e) {
        log.error("Could not locate SessionFactory in JNDI", e);
        throw new IllegalStateException("Could not locate SessionFactory in JNDI");
    }
}

@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
public Set<Client> getClients() {
    return this.clients;
}

......
}

and in Client, I set:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
public User getUser() {
    return this.user;
}

THe SessionFactory is defined in root-context.xml. In this way, I should be able to get clients from detached User object, right? However, when I ran this code:

results.addAll(userDAO.findById(id).getClients());

it returned the following exception:

WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: com.hersbitcloud.cancercloud.models.Client["user"]->com.hersbitcloud.cancercloud.models.User["clientss"]->org.hibernate.collection.internal.PersistentSet[0]->com.hersbitcloud.cancercloud.models.Client["user"]->com.hersbitcloud.cancercloud.models.User["clients"]->org.hibernate.collection.internal.PersistentSet[0]-
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

The stack trace is extremely long, which I think, means when I get the User, it fetches Client at the same time because it is EAGER. Then the User Object is fetched again as inner object of Client, even it is set as LAZY. This process go back and froth, never stop.

I understand LAZY only fetch stuffs in the session. My question is, why the session to User never expired?

Steven Luo
  • 2,350
  • 3
  • 18
  • 35
  • Are you using JSON? http://stackoverflow.com/questions/32354856/infinite-recursion-with-jackson-json-spring-mvc-4-2-and-hibernate-jpa-issue – RubioRic Apr 25 '16 at 04:37

1 Answers1

2

It is because your models (entities) have bidirectional mapping. When Jackson tries to serialize objects it faces user.getClients()[0].getUser().getClients().... recursive chain. Because you directly use entities on the presentation layer.

You can do few things.

  1. Use DTOs
  2. Use @JsonIgnore on your entity directly (I don't prefer DAO/MVC mixing)
  3. May be more options

This answer has better ways to do it

Community
  • 1
  • 1
sura2k
  • 7,365
  • 13
  • 61
  • 80
  • It solves the problem, thanks. I think the problem is the Jackson data mapping. It tries to retrieve everything. If using a DTO, everything's fine. BTW, `@JsonIgnore` works fine too. – Steven Luo Apr 26 '16 at 01:06