Dave
Dave

Reputation: 119

Sessions with JPA

When I load a lazy loaded list in a rich:dataTable I always get the "failed to lazily initialize a collection of role" error.

This is of course because the session is closed at this state.

My Question how can I use sessions by just using JPA (no spring etc.). Do i really need the HibernateUtil stuff or Hibernate.Initialize(..). I would rather not use this Hibernate specific things, just plain JPA. And no EAGER fetch.

My current code:

Entity:

@SuppressWarnings("serial")
@Entity
@Table(name = "user", uniqueConstraints = {
    @UniqueConstraint(columnNames = "username"),
    @UniqueConstraint(columnNames = "email")})
public class User implements Serializable {

...

@OneToMany(mappedBy="user", fetch=FetchType.LAZY)
  private List<UserTournament> userTournament = new ArrayList<UserTournament>();

...

}

DAO:

@Stateless(name = "usercontroller")
public class UserController implements UserControllerInterface {

  @PersistenceContext
  private EntityManager em;

...

  @Override
  public List<UserTournament> getUserTournaments(Integer userid) {
    User user = loadUser(userid);
    return user.getUserTournament();
  }

...

}

Named Bean:

@Named("myTournBean")
@ViewScoped
public class MyTournamentsBean implements Serializable {

  @EJB
  private UserControllerInterface userController;

  private List<UserTournament> tournaments;

...

  @PostConstruct
  public void init() {
...
    tournaments = userController.getUserTournaments(userid);
  }
...
}

xhtml:

<h:panelGrid columns="3" columnClasses="titleCell">

    <rich:dataScroller for="table" maxPages="5" />
        <rich:dataTable value="#{myTournBean.tournaments}" var="tourn"
                            id="table" rows="10">
            <rich:column>
            <f:facet name="header">
            <h:outputText value="Id" />
            </f:facet>
            <h:outputText value="#{tourn.id}" />
            </rich:column>
        </rich:dataTable>
    <rich:dataScroller for="table" maxPages="5" />
</h:panelGrid>

EDIT:

The link form @BoristheSpider was very helpful. I'm not completely through it but this already solved my issue:

@Stateful
@ConversationScoped
public class Service
{
    @PersistenceContext(type = PersistenceContextType.EXTENDED)
    private EntityManager em;
}

Upvotes: 2

Views: 1178

Answers (1)

JB Nizet
JB Nizet

Reputation: 691735

If you don't want you class to be dependant on Hibernate, then create a utility class and depend on this utility class to initialize your associations:

public class JPAUtils {
    public static void initialize(...) {
        Hibernate.initialize(...);
    }
}

And when you change your JPA provider (which has almost 0 chance to happen), then rewrite this method using the corresponding helper class of your new JPA provider, or by simply calling a method of the object or collection to initialize.

Upvotes: 1

Related Questions