开发者

Hibernate Proxy Problem

I'm sorry to ask such a basic question but I could not find a clear answer in others' questions:

I have a class Foo

public class Foo {
  private Integer id;
  private String name;
  private Bar bar;
  // getters and setters
}

And another class Bar

public class Bar {
  private Integer id;
  private String name;
  private Set<Foo> foos;

  // getters and setters 
}

I have a ManagedBean which has a ManagedProperty like this:

public class FooBean {
 @ManagedProperty(value = "{param.barId}"
 private Integer barId;
 private Bar bar;
 private Foo foo;

 public FooBean() {
 }

 @PostConstruct
 public void initialize() {
  SessionFactory factory = new Configuration().configure().buildSessionFactory();   
    if barId != null) {
      foo = new Foo();

      Session session = factory.openSession();

      try {
        session.beginTransaction();

        bar = (Bar) session.load(Bar.class, barId);        

        foo.setBar(bar);

        session.getTransaction().commit();
      } catch (Exception ex) {
        Transaction tx = session.getTransaction();
        if (tx.isActive()) {
          tx.rollback();
        }                
      } finally {
        session.close();
      }
    }
 }
}

And in my facelet I try to show the data this开发者_开发知识库way:

<h:outputText value="#{fooBean.foo.bar.name}" />

Which doesn't work! but If I add bar.getName() to my initialize method (after loading the bar) it works fine! Why? And what is a best practice alternative?


add

lazy="false"

for the name property in your hibernate mapping xml.


The problem is that you are using

session.load(...)

This method assumes that the entity exist. So it does not have to query the database to check and can simply return a proxy that will load the entity later. If you call a Getter method of the Bar object you will initialize the proxy and you can make other calls later without database access.

If you use

session.get(...)

this should not happen, because Hibernate will get the entity from the database immediately to check if it exists and does not return a proxy.


You can do these:

  • Use eager initialization in your schema (if you use annotations then use 'fetch = FetchType.EAGER'), this defines that everytime a Foo instance is retreived from the DB Foo.bar will be fetched.
  • Write a jpa query which tells the API that foo.bar should be fetched in this query, something like this: 'From Foo foo join fetch foo.bar'

The first option is global, the second fetches the foo.bar for that query.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜