Проблема Hibernate Proxy - PullRequest
       33

Проблема Hibernate Proxy

1 голос
/ 11 января 2011

Извините, что задаю такой простой вопрос, но я не смог найти четкого ответа на вопросы других:

У меня есть класс Foo

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

И ещекласс Bar

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

  // getters and setters 
}

У меня есть ManagedBean с ManagedProperty, подобным этому:

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

И в моем лицевом окне я пытаюсь показать данные таким образом:

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

Что не работает!но если я добавлю bar.getName() к моему методу инициализации (после загрузки панели), он будет работать нормально!Зачем?А что является альтернативой лучшей практики?

Ответы [ 3 ]

3 голосов
/ 11 января 2011

Проблема в том, что вы используете

session.load(...)

Этот метод предполагает, что сущность существует. Таким образом, он не должен запрашивать базу данных для проверки и может просто вернуть прокси, который позже загрузит объект. Если вы вызываете метод Getter объекта Bar, вы инициализируете прокси-сервер и позже сможете выполнять другие вызовы без доступа к базе данных.

Если вы используете

session.get(...)

этого не должно происходить, потому что Hibernate немедленно получит объект из базы данных, чтобы проверить, существует ли он, и не возвращает прокси.

3 голосов
/ 11 января 2011

добавить

lazy="false"

для свойства name в xmlnate mapping hml.

1 голос
/ 11 января 2011

Вы можете сделать это:

  • Используйте энергичную инициализацию в своей схеме (если вы используете аннотации, затем используете 'fetch = FetchType.EAGER'), это определяет, что каждый раз, когда экземпляр Foo извлекается из БД Foo.bar, будет выбираться.
  • Напишите jpa-запрос, который сообщает API, что foo.bar должен быть выбран в этом запросе, что-то вроде этого: 'Из Foo foo join fetch foo.bar'

Первый параметр является глобальным, второй выбирает foo.bar для этого запроса.

...