2012-03-03 3 views
1

Я пытаюсь решить мою проблему с LazyLoading, с которой я работал в прошлом с помощью fetchType EAGER. Но это не может быть окончательным решением.LazyLoading with spring and hibernate

Я попытался привести пример, который не имеет большого значения, как это есть, но демонстрирует мою проблему: У меня есть компания, а люди - @ManyToOne по композиции. Теперь, когда я пытаюсь получить доступ к personList с помощью калькулятора, я получаю это исключение:

Schwerwiegend [javax.enterprise.resource.webcontainer.jsf.context] (http--127.0.0.1-8080-4) javax.el.ELException: /tablePersons.xhtml @31,76 value=" #{calculator.getPersonCount(_var)}": 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: business.domain.Company.personList, no session or session was closed 

Может быть кто-то может помочь мне решить это?

tablePersons.xhtml:

<p:dataTable var="_var" value="#{facade.companies}"> 
<p:column> 
<h:outputText value="#{calculator.getPersonCount(_var)}" /> 

отступающие фасадов:

@Named 
@RequestScoped 
class Facade() { 
    @Inject 
    Dao dao; 

    List<Company> companies; 

    @PostConstruct 
    init() { 
     companies = Dao.findByNamedQuery("Companies.ALL"); 
    } 
} 


@Named 
@RequestScoped 
class Calculator { 
    int getPersonCount(Company c) { 
     return c.getPersonList().size(); //EX 
    } 
} 

Crud сервис:

@Stateless 
@Transactional 
class Dao() { 
    @PersistenceContext 
    private EntityManager em; 

    //CRUD 
} 

Entity:

@Entity 
@NamedQueries({ 
    @NamedQuery(name = Company.ALL", 
       query = "SELECT c FROM Company c") 
}) 
class Company { 
    @OneToMany(cascade = CascadeType.ALL) // fetch=FetchType.EAGER <-ugly, but would work 
    List<Person> personList = new LinkedList<Person>(); 
} 

я уже настроил Spring OpenEntityManager в web.xml:

<filter> 
    <filter-name>OpenEntityManagerInViewFilter</filter-name> 
    <filter-class> 
     org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter 
    </filter-class> 
    <init-param> 
     <param-name>entityManagerFactoryBeanName</param-name> 
     <param-value>entityManagerFactory</param-value> 
    </init-param> 
</filter> 
<filter-mapping> 
    <filter-name>OpenEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

Тем не менее он не работает. Но я не знаю, почему! Может быть, кто-то знает больше?

tyvm

ответ

1

Для решения LazyInitializationException происходит в виде слое, у вас есть следующие варианты:

  1. Использования «Открыть EntityManager в виде» шаблоны для ленивых нагрузок неинициализированного лица, в представлении. Кажется, вы так поступаете, но я понятия не имею, почему это провалилось.

  2. Перед возвратом в представление всегда инициализируйте все объекты, которые должны отображаться в представлении.

Вы можете использовать Hibernate.initialize(), чтобы заставить инициализацию Company.personList:

class Facade() { 
    @Inject 
    Dao dao; 

    List<Company> companies; 

    @PostConstruct 
    init() { 
     companies = Dao.findByNamedQuery("Companies.ALL"); 
     Hibernate.initialize(companies.getPersonList()); 
    } 
} 

Или использовать fetch join для извлечения personList вместе с company.it вызовет возврат Компании объект полностью имеют свои personList инициализируется.

@Entity 
@NamedQueries({ 
    @NamedQuery(name = "Company.ALL",query = "SELECT c FROM Company c") 
    @NamedQuery(name = "Company.ALL.WithPerson",query = "SELECT c FROM Company c join fetch c.personList") 
}) 
class Company { 
    @OneToMany(cascade = CascadeType.ALL) // fetch=FetchType.EAGER <-ugly, but would work 
    List<Person> personList = new LinkedList<Person>(); 
} 

Затем извлечь компанию, используя именованный запрос «Company.ALL.WithPerson»

+1

мужчина спасибо за ваш ответ, я действительно ценю это !! Тем временем я обнаружил, что это сработает, если я буду использовать '@PersistenceContext (type = PersistenceContextType.EXTENDED)', но я не знаю, является ли это хорошей практикой? В противном случае я бы выбрал ваше решение с инициализацией в postconstruct. – membersound

+0

Добро пожаловать. У меня не так много опыта в '@PersistenceContext (type = PersistenceContextType.EXTENDED)'. поэтому я не могу прокомментировать это. Но для шаблона «Open EntityManager in View» или «Open Session in View» я лично не одобряю его.Вы можете отправить его по адресу http://stackoverflow.com/questions/1103363/why-is-hibernate-open-session-in-view-considered-a-bad-practice –

Смежные вопросы