1

3つのspring+JPAプロジェクトがあります...ベースプロジェクトA、プラグインプロジェクトB、および実際のプロジェクトCです。Cでは、他の両方のプロジェクトがA.jarおよびB.jarとしてインポートされます。各プロジェクトには、独自のApplicationContext.xmlがあります。リーフプロジェクト、つまりCは、proeject-Aのappcontext.xmlで説明されているように、カスタムの場所にpersistence.xmlを持っています(プロジェクトAを起動すると、クラスパス全体でappcontext.xmlとpersistence.xmlが検索されるため、Bからxmlをロードできます。およびC)。

以下は私の構成、ApplicationContext.xmlです-プロジェクトAで

<bean id="jpaQueryManager" class="com.motherframework.base.dao.jpa.JPAQueryManager">
    <property name="jpaTemplate" ref="jpaTemplate"/>
</bean>

<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <!-- <property name="persistenceUnitManager" ref="pum"/>
    <property name="persistenceUnitName" value="SchoolWebsitePersistenceUnit"/> -->
    <property name="persistenceXmlLocation" value="classpath*:configuration/xml/persistence.xml"/>
    <!-- <property name="persistenceUnitPostProcessors">
      <list>
        <bean class="com.motherframework.base.dao.jpa.EntityScanner"/>
      </list>
    </property> -->
    <property name="dataSource"><ref bean="dataSource"/></property>
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true"/>
        <property name="generateDdl" value="true"/>
        <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
      </bean>
    </property>
</bean>

そしてこれは私のpersistence.xmlです

<persistence-unit name="SchoolWebsitePersistenceUnit" transaction-type="RESOURCE_LOCAL">

    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>com.motherframework.plugin.school.entity.Account</class>
    <class>com.motherframework.plugin.school.entity.Module</class>
    <class>com.motherframework.plugin.school.entity.NavigationMenu</class>
    <class>com.motherframework.plugin.school.entity.User</class>


    <properties>
        <property name="dialect" value="org.hibernate.dialect.SQLServerDialect"/>
        <property name="hibernate.connection.autocommit" value="true"/>
        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.archive.autodetection" value="class, hbm"/>
    </properties>

</persistence-unit>

これで、クライアントクラス(メインメソッド)から、@transactional Service-DAOレイヤーを使用してエンティティ(ユーザーなど)をフェッチしています。

User u = ((TestService) ApplicationContext.getBean("testService")).fetchUser();
// FROM User u WHERE u.id=1  (Note: no INNER JOIN u.account)

print(u.getAccount())

NULLが返されるはずですが、例外がスローされます。

DEBUG DefaultListableBeanFactory:241 - Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
 DEBUG AnnotationTransactionAttributeSource:106 - Adding transactional method 'fetchUser' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
DEBUG DefaultListableBeanFactory:241 - Returning cached instance of singleton bean 'jpaTxManager'
DEBUG JpaTransactionManager:365 - Creating new transaction with name [com.motherframework.plugin.test.service.TestService.fetchUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
DEBUG JpaTransactionManager:323 - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@d964af] for JPA transaction
DEBUG JpaTransactionManager:355 - Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle: jdbc:mysql://localhost:3306/schooldb, UserName=scott@localhost, MySQL-AB JDBC Driver]
DEBUG TransactionSynchronizationManager:183 - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@45378f] for key [org.apache.commons.dbcp.BasicDataSource@181b3d4] to thread [main]
DEBUG TransactionSynchronizationManager:183 - Bound value [org.springframework.orm.jpa.EntityManagerHolder@29d65b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@b8176d] to thread [main]
DEBUG TransactionSynchronizationManager:258 - Initializing transaction synchronization
DEBUG TransactionInterceptor:381 - Getting transaction for [com.motherframework.plugin.test.service.TestService.fetchUser]
DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@29d65b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@b8176d] bound to thread [main]
DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@29d65b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@b8176d] bound to thread [main]
DEBUG TransactionSynchronizationManager:139 - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@29d65b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@b8176d] bound to thread [main]
Hibernate: select user0_.id as id3_, user0_.accountId as accountId3_, user0_.email as email3_, user0_.loginId as loginId3_, user0_.name as name3_, user0_.password as password3_ from User user0_ where user0_.id=1
DEBUG TransactionInterceptor:410 - Completing transaction for [com.motherframework.plugin.test.service.TestService.fetchUser]
DEBUG JpaTransactionManager:925 - Triggering beforeCommit synchronization
DEBUG JpaTransactionManager:938 - Triggering beforeCompletion synchronization
 DEBUG JpaTransactionManager:752 - Initiating transaction commit
DEBUG JpaTransactionManager:462 - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@d964af]
DEBUG JpaTransactionManager:951 - Triggering afterCommit synchronization
DEBUG JpaTransactionManager:967 - Triggering afterCompletion synchronization
DEBUG TransactionSynchronizationManager:311 - Clearing transaction synchronization
DEBUG TransactionSynchronizationManager:229 - Removed value [org.springframework.orm.jpa.EntityManagerHolder@29d65b] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@b8176d] from thread [main]
DEBUG TransactionSynchronizationManager:229 - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@45378f] for key [org.apache.commons.dbcp.BasicDataSource@181b3d4] from thread [main]
DEBUG JpaTransactionManager:548 - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@d964af] after transaction
DEBUG EntityManagerFactoryUtils:329 - Closing JPA EntityManager
856 [main] ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at            org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
at     org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at      com.motherframework.plugin.school.entity.Account_$$_javassist_3.toString(Account_$$_javassist_3.java)
at java.lang.String.valueOf(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at 

私のエンティティマネージャーが閉じていることがわかります。そのため、ユーザーのアカウントを取得しようとすると例外が発生します。理解できますが、エンティティマネージャーが閉じている場合は、なぜそれを実行しようとしているのでしょうか。それを止める方法は?設定に問題はありますか?

もう1つ、私が使用しているentitymanagerfactoryは、実稼働環境(およびTomcat 7)のパブリックWebアプリケーションに適していますか?

前もって感謝します..:)

ありがとうNizet..つまり、EntityManagerが閉じられているため、私のPersistenceContextはすでに閉じられています。しかし、エンティティが実際にPersistenceContextから外れている場合、なぜその関係をフェッチしようとする必要があるのでしょうか?..それは単純なPOJOであり、@Entityではありません。2番目の問題については、はい、私はそれを逃しました

<tx:annotation-driven transaction-manager="jpaTxManager"/>
<bean id="jpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory"><ref bean="entityManagerFactory"/></property>
    <property name="dataSource"><ref bean="dataSource"/></property>
</bean>

Entitymanagerのタイプとtransactionmanagerを確認してください...これらは本番環境に適していますか?

これは私のDSです:

<bean id="dataSource" destroy-method="close"   class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${motherframework.configuration.db.driver}" />
<property name="url" value="${motherframework.configuration.db.url}" />
<property name="username" value="${motherframework.configuration.db.username}" />
<property name="password" value="${motherframework.configuration.db.password}" />

しかし、永続コンテキストは閉じられていますが、「user」オブジェクトは、通常のPOJOクラスとは異なるいくつかのプロパティを保持していることを意味しますか?

4

1 に答える 1

5

ユーザーはアカウントと関連付けられています。アカウントは遅延ロードされます。user.getAccount().getName()これは、たとえばアカウント ( ) でメソッドを初めて呼び出すと、Hibernate がデータベースからアカウントの状態をロードし、アカウントの名前を返すことを意味します。エンティティ マネージャが開いている間のみ、それを行うことができます。それ以外の場合は、データベースへの接続がなくなります。

null を返すことはできません: null を返すと、このユーザーにはアカウントがありません。これは誤りです。

エンティティ マネージャーが閉鎖された後にアカウントにアクセスする場合は、アカウントを閉鎖する前にアカウントを初期化する必要があります。それを回避する方法はありません。

あなたの構成に関しては、いいえ、本番環境の準備ができていません:

  • showSql は false である必要があります
  • hibernate.show_sql は false にする必要があります
  • generateDdl は false にする必要があります
  • hibernate.connection.autocommit は false にする必要があります
  • 非常に重要な部分であるデータソース定義を表示していません
于 2012-08-03T11:35:35.887 に答える