2012-07-02 2 views
2

J'ai eu un problème en utilisant CrudRepository. Exemple: j'ai deux entités, l'entité A a une collection de l'entité B.Printemps 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 
} 

puis j'ai 2 dépôts.

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

mais quand je suis arrivé, je suis un org.hibernate.LazyInitializationException, comment puis-je éviter cela?

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

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

est ici le 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" /> 

ici est le 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 (la collection) ne seraient pas chargés, et toujours jeter org.hibernate.LazyInitializationException: échec de l'initialisation paresseuse d'une collection de rôles: aucune session ou session n'a été fermée

Merci d'avance !!

Répondre

0

Voici la solution:

Je ne peux pas accéder à l'objet sur ma couche Web, je devrais accéder aux objets de chargement paresseux dans la couche de service, qui devrait être dans une transaction.

+1

Vous devez pouvoir accéder à des objets paresseusement chargés dans une ** vue Web ** en utilisant ['openSessionInViewFilter'] (http://static.springsource.org/spring/docs/2.5.x/api/org/ springframework/orm/hibernate3/support/OpenSessionInViewFilter.html) car il maintient la session ouverte jusqu'à ce que la requête se termine complètement. En outre, vous ne devriez pas utiliser 'singleSession = true'. Cela provoque des problèmes (il ne fournit cependant pas de cache de premier niveau pour l'ensemble de la requête). – Lion

2

Vous devez utiliser démarrer une transaction, de préférence via Declarative Transaction Management de Spring.

Dans la plupart des cas:

  • définir un TransactionManager dans votre XML
  • Ajouter à votre XML <tx:annotation-driven />
  • annoter votre méthode de service avec @Transactional

Vous pouvez trouver un exemple de configuration dans la section Using @Transactional

+0

Salut Sean, merci de me répondre, mais j'ai déjà fait, tout. Je viens d'ajouter plus de détails. S'il vous plait, j'ai besoin de votre aide avec ceci. – Jaiwo99

Questions connexes