2012-07-02 5 views
2

У меня проблема с использованием CrudRepository. Пример: у меня есть два объекта, у субъекта A есть совокупность объекта B.Spring CrudRepository throws org.hibernate.LazyInitializationException

class A { 
    int id; 
    int name; 
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    Set<B> bs; 
    // getters and setters 
} 
class B { 
    int id; 
    int name; 
    @ManyToOne(mappedBy="bs") 
    A a; 
    // getters and setters 
} 

После этого у меня есть 2 репозитория.

class ARepository extends CrudRepository<A, int>{} 
class BRepository extends CrudRepository<B, int>{} 

, но когда я получил это, я получил org.hibernate.LazyInitializationException, как я могу избежать этого?

@Service 
@Transactional(readOnly=true) 
class ServiceImpl implements Service { 
@Resource ARepository ar; 

@Override 
A a = ar.findOne(int id); 
} 

вот applicationContext.xml:

<jpa:repositories base-package="com.myproject.repository" /> 

<context:component-scan base-package="com.myproject.*" /> 
<context:annotation-config /> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" > 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="persistenceUnitName" value="keep-apm" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="true" /> 
      <property name="generateDdl" value="true" /> 
      <property name="database" value="POSTGRESQL"/> 
      <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect"/> 
     </bean> 
    </property> 
</bean> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="username" value="root" /> 
    <property name="password" value="root" /> 
    <property name="driverClassName" value="org.postgresql.Driver" /> 
    <property name="url" value="jdbc:postgresql://127.0.0.1:5432/db" /> 
</bean> 
<bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory"> 
</bean> 
<tx:annotation-driven transaction-manager="transactionManager" /> 

здесь является web.xml

<filter> 
    <filter-name>openSessionInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> 
    <init-param> 
     <param-name>singleSession</param-name> 
     <param-value>true</param-value> 
    </init-param> 

</filter> 
<filter-mapping> 
    <filter-name>openSessionInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<filter> 
    <filter-name>struts2</filter-name> 
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>struts2</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 
<listener> 
    <listener-class>com.myproject.util.LogLocator</listener-class> 
</listener> 

<welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
</welcome-file-list> 

a.bs (сборник) не будет загружен, и всегда выбрасывать a org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию роли: сеанс или сеанс не закрыты

Спасибо заранее!

ответ

0

Вот решение:

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

+1

Вы должны иметь доступ к лениво загруженным объектам в ** веб-представлении ** с помощью ['openSessionInViewFilter'] (http://static.springsource.org/spring/docs/2.5.x/api/org/ springframework/orm/hibernate3/support/OpenSessionInViewFilter.html), потому что он держит сессию открытой, пока запрос не завершится полностью. Кроме того, вы не должны использовать 'singleSession = true'. Это вызывает проблемы (однако он не обеспечивает кеш первого уровня для всего запроса). – Lion

2

Вам нужно использовать начало транзакции, предпочтительно по весне Declarative Transaction Management.

В большинстве случаев:

  • определяют TransactionManager в вашем XML
  • добавить это к вашему XML <tx:annotation-driven />
  • аннотировать метод обслуживания с @Transactional

Вы можете найти установку образца в разделе Using @Transactional

+0

Привет, Шон, спасибо, что ответил мне, но я уже сделал, все. Я просто добавил более подробную информацию. Пожалуйста, помогите мне с этим. – Jaiwo99

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