我在配置一个使用JPA和Hibernate进行单元测试的Spring应用程序时遇到问题.
我有2个persistence.xml文件,一个用于生产,一个用于单元测试.
用于检测:
用于检测:
区别在于单元测试我不使用任何JTA(全局事务),我只使用本地事务.
生产的d簧配置是:
单元测试的d簧配置:
我花了相同的时间来决定这个配置,应用程序需要全局事务,因为我们在JMS和DB之间有事务,但在单元测试中我只定义了本地事务,所以我在测试应用程序时受到限制.
有了这个限制,我定义了我的单元测试.
现在我遇到了Hibernate和LAZY加载关系的问题.在单元测试中,EntityManager会话在查找方法之后关闭,然后LAZY加载的代理不起作用.(根据预期,这在Hibernate中是定义的)
我的问题是Bean PersistenceAnnotationBeanPostProcessor,它确实为单元测试设置了任何unitname,并且每当他找到注释@PersistenceContext时,他都会插入一个新的Entitymanger,该Entitymanger是从spring配置中定义的EntityManagerFactory创建的,用于测试.
现在,单元测试还有一个@PersistenceContext entityManager成员和DAO类:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:testConfiguration.xml"})@TransactionConfiguration(transactionManager = "transactionManager",defaultRollback = true)@Transactionalpublic class ConnectionTest { @PersistenceContext EntityManager entityManager; Logger log = Logger.getLogger(ConnectionTest.class); @Resource(name = "syDbVersionDao") SyDbVersionDao dbVersionDao; @Test public voID testChanging() { String oldVer = dbVersionDao.getCurrentVersion(); assertNotNull(oldVer); }} @Component public class SyDbVersionDao extends SyDbVersionHome { @PersistenceContext private EntityManager entityManager; public String getCurrentVersion() { SyDbVersion res = getLastRecord(); if (res == null) return ""; return res.getVersion(); } public SyDbVersion getLastRecord(){ query query = entityManager.createquery("from SyDbVersion v order by v.installationDate desc"); query.setMaxResults(1); return (SyDbVersion) query.getSingleResult(); } } /** * Home object for domain model class SyDbVersion. * @see com.tsy@R_301_6563@s.ac.fIDs.web.persistence.jpa.SyDbVersion * @author Hibernate Tools,generated! */ @Stateless public class SyDbVersionHome { private static final Log log = LogFactory.getLog(SyDbVersionHome.class); @PersistenceContext private EntityManager entityManager; public voID persist(SyDbVersion transIEntInstance) { log.deBUG("persisting SyDbVersion instance"); try { entityManager.persist(transIEntInstance); log.deBUG("persist successful"); } catch (RuntimeException re) { log.error("persist Failed",re); throw re; } } public voID remove(SyDbVersion persistentInstance) { log.deBUG("removing SyDbVersion instance"); try { entityManager.remove(persistentInstance); log.deBUG("remove successful"); } catch (RuntimeException re) { log.error("remove Failed",re); throw re; } } public SyDbVersion merge(SyDbVersion detachedInstance) { log.deBUG("merging SyDbVersion instance"); try { SyDbVersion result = entityManager.merge(detachedInstance); log.deBUG("merge successful"); return result; } catch (RuntimeException re) { log.error("merge Failed",re); throw re; } } public SyDbVersion findByID( long ID) { log.deBUG("getting SyDbVersion instance with ID: " + ID); try { SyDbVersion instance = entityManager.find(SyDbVersion.class,ID); log.deBUG("get successful"); return instance; } catch (RuntimeException re) { log.error("get Failed",re); throw re; } } }
SyDbVersionHome类是使用DB和Entity类中的Hibernate Tools生成的.
现在的问题是这条线:
SyDbVersion instance = entityManager.find(SyDbVersion.class,ID);
每次当我从find方法返回时,会话都会关闭,因此懒惰的成员不再可用.
我正在考虑使用持久性单元名称正确配置PersistenceAnnotationBeanPostProcessor的方法,但是bean正在搜索JNDI中的持久性单元,我找不到为持久性单元注册JNDI条目的适当时间.
在生产中,因为我设置了持久性PersistenceAnnotationBeanPostProcessor,然后正确地共享EntityManager,并且每次查找后都不会关闭会话.
另一种解决方案是使用OpenEJB或embedded-glassfish在单元测试中模拟/拥有应用服务器(将成为集成测试).
我必须在d簧配置或代码中修改哪些选项以避免单元测试中出现此问题?
最佳答案我发现了我的代码问题.问题是当加载ApplicationContext然后我在一个Bean对象中缓存一些JPA实体.后来在测试方法中(在另一个事务中)我正在访问这个延迟加载关系.当然这不是设计工作,你必须在同一个事务上下文中访问加载延迟加载的关系,否则你会得到一个像我的情况一样的异常.解:
>使用而不是LAZY装载,EAGER装载.
>在返回之前显式初始化所需的所有关联和集合.然后你也可以在另一个交易中访问它们.
节点n = // ..获取节点
状态,Hibernate.initialize(N); //初始化’parent’,类似于getParent.
状态,Hibernate.initialize(n.getChildren()); //将延迟集合传递给要初始化的会话.
>尝试保持会话/事务处于打开状态,直到您需要它为止.在我的情况下,这是不可能的,没有任何意义. 总结
以上是内存溢出为你收集整理的使用Hibernate配置Spring JPA应用程序进行单元测试(延迟加载)全部内容,希望文章能够帮你解决使用Hibernate配置Spring JPA应用程序进行单元测试(延迟加载)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)