Abh*_*jee 1 spring hibernate jpa lazy-loading entitymanager
我有三个spring + JPA项目......一个基础项目A,一个插件项目B和实际项目C.在C中,两个其他项目都作为A.jar和B.jar导入.每个项目都有自己的ApplicationContext.xml.叶子项目即C将其persistence.xml置于自定义位置,如proeject-A中的appcontext.xml中所述(启动项目A在整个类路径中查找appcontext.xml和persistence.xml,因此能够从B加载xmls)和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>
Run Code Online (Sandbox Code Playgroud)
这是我的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>
Run Code Online (Sandbox Code Playgroud)
现在从我的客户端类(主要方法)我使用@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())
Run Code Online (Sandbox Code Playgroud)
它应该给我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
Run Code Online (Sandbox Code Playgroud)
您可以发现我的实体管理器已关闭,因此如果它试图在用户上获取帐户,它会给出一个例外....我理解......但如果实体管理器关闭那么为什么它会尝试这样做?怎么阻止它?配置有问题吗?
还有一件事是,我正在使用的实体工具是否适用于生产环境(以及tomcat 7)中的公共Web应用程序?
提前致谢..:)
谢谢Nizet ..你的意思是我的PersistenceContext已经关闭,因为EntityManager已关闭.但是如果实体真的没有PersistenceContext那么它为什么要尝试获取它的关系呢?那么它就是一个简单的POJO,而不是@Entity ..还有吗?对于第二个问题,是的,我错过了
<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>
Run Code Online (Sandbox Code Playgroud)
请检查我的Entitymanager类型和事务管理器......它们适合生产吗?
这是我的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}" />
Run Code Online (Sandbox Code Playgroud)
但你是否想要这样说,虽然持久化上下文已经关闭,但"用户"对象仍然拥有一些属性,这使得它与普通的POJO类不同?
您的用户与帐户有关联.该帐户是懒惰的.这意味着第一次调用account(user.getAccount().getName()
)上的任何方法时,Hibernate将从数据库加载帐户的状态,并返回帐户的名称.它只能在实体管理器打开时执行此操作,否则它不再与数据库建立任何连接.
它不能返回null:返回null意味着:此用户没有帐户,这是错误的.
如果要在实体管理器关闭后访问该帐户,则需要在关闭之前初始化该帐户.没有办法解决这个问题.
关于你的配置,不,它还没有准备好生产:
归档时间: |
|
查看次数: |
3241 次 |
最近记录: |