0

I have the following working without FetchType.LAZY:

@Entity
public class Test {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    @ManyToOne  
    @JoinColumn(name = "lazy_id")
    private Lazy lazy;

    //getters and setters
}

@Entity
public class Lazy {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    //getters and setters
}

And the query method:

public List<Test> all() {
    try {
        return em.createQuery("FROM Test t").getResultList();
    } catch (NoResultException e) {
        return null;
    }
}

This is the JSON result:

[{"id":1,"text":"test 1","lazy":{"id":1,"text":"lazy 1"}},
{"id":2,"text":"test 2","lazy":{"id":2,"text":"lazy 2"}}]

However I want to return just the id and text data, so I tried to change the @ManyToOne(fetch = FetchType.LAZY)

Then I get this errors:

Severe:   Generating incomplete JSON
Severe:   org.hibernate.LazyInitializationException: could not initialize proxy [model.Lazy#1] - no Session

I could do something like changing the query to fetch only the fields I want:

public List<Test> all() {
    try {
        return em.createQuery("SELECT t.id, t.text FROM Test t").getResultList();
    } catch (NoResultException e) {
        return null;
    }
}

But then my response in the JavaScript front end is:

[[1,"test 1"],[2,"test 2"]]

Not a array of objects anymore, mapping everything giving the amount of entities I have is far from ideal.

Most of the content I found is how to fetch the data afterwards, which is not my concern, all I need is to send only fields I want in the first place. I`m not sure whether the EJB @TransactionAttribute should be used or not, I couldn't find a working example. I also tried to change the strategy to a @OneToMany in the Lazy class but to no avail.

Eduardo
  • 277
  • 1
  • 6
  • 17

1 Answers1

0

Since your question dates back a bit, I hope it's still relevant for you:

If you declare a mapping as lazy (or it is like that by the default behaviour), JPA won't fetch it until it is accessed. So your Lazy class will only be accessed if JSON tries to convert the whole thing and at that point it seems that you no longer have an open session, so the data can't be fetched and will result in an org.hibernate.LazyInitializationException.

If you stick with a lazy mapping (which is in general mostly fine), you have to explicitely fetch or access it, if you need the data for an use case.

Check out Vlad's excellent explanation on the topic.

Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96
  • Yeah, I'm indeed using the DTO design pattern with JPA Projections, it is all I could find, but it is still pretty terrible. I was trying to find a way to make Jersey/Jackson to understand the FetchType.LAZY, but it was so unsuccessful that I put it aside for now. If I ever figure it out I'll post the answer here. – Eduardo Dec 13 '18 at 21:50