Конвертировать сущность Hibernate в json, используя JSONArray.fromObject - PullRequest
2 голосов
/ 02 февраля 2011

У меня проблема с преобразованием данных в json.

Session session = sessionFactory.openSession();       
Affiliate affiliate = (affiliate) session.get( Affiliate , pk );
session.close();
JSONArray.fromObject(affiliate);

отладчик, показывающий, что строка была выбрана.
но я получаю это исключение при попытке преобразовать в строку json:

Exception in thread "main" net.sf.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.affiliates.hibernate.Affiliate.employees, no session or session was closed
at net.sf.json.JSONObject._fromBean(JSONObject.java:959)    ...

это мой филиал

    @Entity(name="AFFILIATE")
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    public class Affiliate extends HibernateBean{ 

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY) 
        @Column(name="AFFILIATE_ID")
        private long id;

        @ManyToOne(targetEntity = Affiliate.class)
        @JoinColumn(name="PARENT_ID")
        private Affiliate parent;



        @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
        @JoinTable(name="EMPLOYEES_AFFILIATES"  , joinColumns = {@JoinColumn(name="AFFILIATE_ID")},inverseJoinColumns={@JoinColumn(name="EMPLOYEE_ID")})
        private Set<Employee> employees = new HashSet<Employee>(0);

 getters and setters...

    }

Спасибо

Ответы [ 2 ]

6 голосов
/ 02 февраля 2011

Ваша коллекция employees помечена как FetchType.LAZY, поэтому она выбирается лениво и не может быть выбрана при закрытии сеанса.

У вас есть несколько вариантов:

  • Если эта коллекция необходима каждый раз, когда вы загружаете объект Affiliate, пометьте его как загруженного:

    @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER) 
    
  • Если вам нужна эта коллекция только в этом конкретном случае,поручить Hibernate загружать его с нетерпением в этом случае:

    • С JOIN FETCH предложение:

      Affiliate affiliate = (Affiliate) session.createQuery(
          "from Affiliate a join fetch a.employees where a.id = :id")
          .setParameter("id", pk).uniqueResult()
      
    • С Hibernate.initialize():

      Affiliate affiliate = (Affiliate) session.get( Affiliate , pk );  
      Hibernate.initialize(affiliate.getEmployees());
      
    • С Выборочные профили

  • Не закрывайте сеанс до готовности ответа.Используйте шаблон Open Session in View .

0 голосов
/ 20 апреля 2012

Никогда не меняйте сущность, если вы не меняете базу данных. Они должны совпадать. Изменение выборки на стремление к сущности саботирует саму идею ленивой загрузки, и в вашем коде могут быть другие места, в которых из-за этого возникают проблемы производительности. Это означает, что если вы изменяете объект, то все и везде ДОЛЖНЫ загружать все эти данные каждый раз, когда они используют этот объект.

То, что вы хотите, это вложенная транзакция. Начните транзакцию в начале вызова метода, который выполняет преобразование JSON, и завершите его в конце метода. Сделайте это, просто добавив транзакционную аннотацию к вызову метода, который содержит это преобразование JSON.

Сделав это, транзакция не будет завершена, когда потребуется информация, и тогда может иметь место ленивая загрузка. Вероятно, в коде есть другие места, где это делается. Ищите их и используйте их как примеры, чтобы основывать свое решение на.

Конечно, если вы будете использовать это в нескольких местах, вы, возможно, захотите вставить его в свой DAO для повторного использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...