加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

使用Hibernate配置Spring JPA应用程序进行单元测试(延迟加载)

发布时间:2020-12-15 01:28:32 所属栏目:大数据 来源:网络整理
导读:我在配置一个使用JPA和Hibernate进行单元测试的Spring应用程序时遇到问题. 我有2个persistence.xml文件,一个用于生产,一个用于单元测试. 用于检测: 用于检测: 区别在于单元测试我不使用任何JTA(全局事务),我只使用本地事务. 生产的弹簧配置是: 单元测试的

我在配置一个使用JPA和Hibernate进行单元测试的Spring应用程序时遇到问题.
我有2个persistence.xml文件,一个用于生产,一个用于单元测试.
用于检测:

用于检测:

区别在于单元测试我不使用任何JTA(全局事务),我只使用本地事务.

生产的弹簧配置是:

 

单元测试的弹簧配置:

我花了相同的时间来决定这个配置,应用程序需要全局事务,因为我们在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)
@Transactional
public 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.tsystems.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在单元测试中模拟/拥有应用服务器(将成为集成测试).

我必须在弹簧配置或代码中修改哪些选项以避免单元测试中出现此问题?

最佳答案
我发现了我的代码问题.问题是当加载ApplicationContext然后我在一个Bean对象中缓存一些JPA实体.后来在测试方法中(在另一个事务中)我正在访问这个延迟加载关系.当然这不是设计工作,你必须在同一个事务上下文中访问加载延迟加载的关系,否则你会得到一个像我的情况一样的异常.

解:

>使用而不是LAZY装载,EAGER装载.
>在返回之前显式初始化所需的所有关联和集合.然后你也可以在另一个交易中访问它们.

节点n = // ..获取节点

状态,Hibernate.initialize(N); //初始化’parent’,类似于getParent.

状态,Hibernate.initialize(n.getChildren()); //将延迟集合传递给要初始化的会话.
>尝试保持会话/事务处于打开状态,直到您需要它为止.在我的情况下,这是不可能的,没有任何意义.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读