【问题标题】:Using Spring+Hibernate for testing purposes使用 Spring+Hibernate 进行测试
【发布时间】:2015-01-20 14:47:09
【问题描述】:

我想进一步澄清我的问题:

  1. 我了解使用 SPring 框架(即容器管理的对象生命周期)和 Hibernate(在 Java 对象和关系数据库系统之间使用 ORM - 阻抗不匹配解决方案)的目的。

  2. 我了解我们如何自动装配对象,并且 Spring 通过查看 applicationContext.xml 文件(如果使用 Hibernate 或任何其他持久性提供程序,除了 persistence.xml 文件)在运行时接管对象的创建和销毁)。

我想做的是:

  1. 我想实现自己的购物服务。我已经有用@Table、@Id、@Column 等注释的实体(项目)来告诉 JPA 这将存储在数据库中。

  2. 我已经有一个由 DaoImpl 类实现的 DAO 接口(目前只有添加和删除方法),我在其中完成了以下操作:

    @Repository
    @Transactional
    public class MyShopDbDaoImpl implements MyShopDbDao {
        // The following named unit will be in my persistence.xml file
        // Which will be placed in src/main/resources/META-INF folder
        @PersistenceContext(unitName="myShopDbDao")
        private EntityManager em;
    
        // Getters for em (simply returns em)
    
        // Setters for em (simply assigns an em supplied in the args.)
    
    
        // Other query method
    }
    
  3. 我还有一个 ShopDbController 控制器类,它使用:

    @Autowired
    // defined in the applicationContext.xml file
    private MyShopDbDao myShopDbDaoImpl
    

我正在努力解决的是对EntityManagerFactoryEntityManager 关系的“理解”以及必须如何管理事务。我知道以下层次结构是理解这一点的主要起点:

  1. 客户端与控制器对话。

  2. 控制器映射请求并让实体管理器对数据库(具有 JUNIT 测试等的测试/本地数据库或实际 SQL 类型的数据库)进行查询和填充。

我所知道的是事务可以手动管理(即开始、提交和关闭会话)或通过 Spring 容器(即在 applicationContext.xml 文件中使用 bean defs)。如何获取有关 entitymanagers 和 entitymanagerfactory 的更多信息以设置我的系统?

我没有发现 Oracle/Spring/Hibernate 的在线文档很有帮助。我需要一个例子和关于 entitymanagerfactory、sessionfactory、entitymanager 和 transactionmanager 之间关系的解释。有人可以帮我解决这个问题吗?

我不需要人牵着我的手,只要把我引向正确的方向。我以前做过 Spring 项目,但从来没有深入了解过一些东西。任何帮助表示赞赏。

【问题讨论】:

  • 阅读这篇优秀的blog 以了解这些概念。
  • @FlyingGuy 我是在用 C++ 编写我的类以与 Hibernate 和 Spring 一起使用吗?
  • @ha9u63ar - 这与 java 语言无关。它与恰好在 java 中实现的两个框架有关,因此我的评论。

标签: spring hibernate jpa


【解决方案1】:

EntityManagerFactory 将获得java.sql.Connection 对象,通过打开/关闭与数据库的新物理连接或使用连接池(c3p0、bonecp、hikari 或任何您喜欢的实现)。获得Connection后,会用它来创建一个新的EntityManagerEntityManager 可以使用这个Connection 与您的对象和数据库交互,并且可以通过调用EntityManager#getTransaction 然后调用EntityTransaction#beginEntityTransaction#commitEntityTransaction#rollback 来管理事务,这些EntityTransaction#rollback 在内部与Connection#begin、@ 一起工作分别为 987654333@ 和 Connection#rollback。这是普通的 JPA,到目前为止,Spring 与此无关。

对于事务管理,Spring 通过使用事务管理器,特别是一个名为 JpaTransactionManager 的类,帮助您避免手动打开/关闭事务。此事务管理器将使用您的EntityManagerFactory 打开和关闭为一组操作创建的EntityManager 的事务。这可以在您的类/方法上使用 XML 配置或 @Transactional 注释来完成。使用这种方法时,您将不再直接使用您的特定类,而是 Spring 将使用 cglib 为您的类创建代理,并使用事务管理器类打开事务,调用您的特定方法并执行最后提交或回滚,具体取决于您的配置。除此之外,Spring 还提供了其他配置,例如只读事务(不允许进行数据修改操作)。

这是上面使用 Spring/Hibernate/JPA 解释的元素的基本配置:

<!--
    Declare the datasource.
    Look for your datasource provider like c3p0 or HikariCP.
    Using most basic parameters. It's up to you to tune this config.
-->
<bean id="jpaDataSource"
    class="..."
    destroy-method="close"
    driverClass="${app.jdbc.driverClassName}"
    jdbcUrl="${app.jdbc.url}"
    user="${app.jdbc.username}"
    password="${app.jdbc.password}" />

<!--
    Specify the ORM vendor. This is, the framework implementing JPA.
-->
<bean id="hibernateVendor"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    showSql="false"/>

<!--
    Declare the JPA EntityManagerFactory.
    Spring provides a class implementation for it.
-->
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    persistenceXmlLocation="classpath*:META-INF/persistence.xml"
    persistenceUnitName="hibernatePersistenceUnit"
    dataSource-ref="jpaDataSource"
    jpaVendorAdapter-ref="hibernateVendor"/>

<!--
    Declare a transaction manager.
    Spring uses the transaction manager on top of EntityManagerFactory.
-->
<bean id="transactionManager"
    class="org.springframework.orm.jpa.JpaTransactionManager"
    entityManagerFactory-ref="entityManagerFactory"/>

【讨论】:

  • 只是一件快速的事情 - jdbc url、用户名和密码 - 我可以在尝试对其运行一些 JUnit 测试时使用一些虚拟变量,而无需将其与实际数据库集成吗?
  • 您可以为您的应用程序配置一个配置,为您的测试配置另一个配置。使用 JUnit 时,可以通过 @ContextConfiguration({ "/path/to/config1", "/path/to/config2" }) 和 on 显式提供配置文件
  • 是的,我明白了——但我想了解如何在不使用 jpaDataSource(即数据库 url 连接等)的情况下运行 JUnit 测试。我相信 RESOURCE_LOCAL tx 类型是合适的?
  • @ha9u63ar 为您的测试使用指向测试数据库的数据源。 RESOURCE_LOCAL 仅用于学习目的,不应用于您的测试或其他原因。
【解决方案2】:

据我所知,您的 em 引用应该是您的数据库的功能代理对象(这个 EntityManager 应该是一个 spring bean,已经配置了所有内容,如 DB url、驱动程序等。除此之外您的任何代码都不应该取决于您拥有的数据库)。你不需要知道你提到的类(entitymanagerfactory sessionfactory transactionmanager)。简单的例子是:

List<MyBean> bean = (List<MyBean>)em.createNamedQuery("select * from mydb").getResultList();

运行 select * 查询并直接获取 MyBean 类型的对象应该很容易,无需您进行任何显式转换(这就是 hibernate 的用途)。

插入类似:

em.persist(myBean);

myBean 是为 Hibernate 注释的东西。

简要介绍一下事务,我发现最好在服务方法上注释 @Transactional(你在整个 dao 上都这样做了)。

【讨论】:

  • 我知道你的意思。我也不想,但如果我不正确理解它们,我将无法设置我的 persistence.xml 文件和 applicationContext.xml 文件。有一系列 bean defs 需要进入 applicationContext.xml 文件 - 我在那里挣扎。或许你能给我看一下xml文件,我会理解得更好。
  • 哦,所以你正在创建这些配置。以为你明白了。
【解决方案3】:

非常笼统:

  • entitymanagerfactory 是负责创建 entitymanager 的对象,它来自 JPA 规范。
  • SessionFactory 是 entitymanagerfactory 的休眠实现
  • session 是 entitymanager 的休眠实现
  • 事务管理器是在您要手动定义事务时管理事务的对象。

所以如果你想使用休眠,使用 SessionFactory 和 session.如果您希望保持“通用”,请使用 EntityManagerFactory。

http://www.javabeat.net/jpa-entitymanager-vs-hibernate-sessionfactory/ http://www.theserverside.com/tip/How-to-get-the-Hibernate-Session-from-the-JPA-20-EntityManager

【讨论】:

  • 感谢您的简短解释-您能否举例说明我应该如何使用这三个设置我的 applicationContext.xml 文件?我在那里挣扎,并收到很多 NPE 和 BeanInstantiationException 消息:(。另外,我将 applicationContext.xml 文件保存在 src/main(或 test)/resources 文件夹中,并将 persistence.xml 文件保存在 src/main(或 test) 中/resources/META-INF 文件夹。
  • EntityManagerFactory 的一个很好的例子:pauliusmatulionis.blogspot.fr/2013/07/… SessionFactory 的一个很好的例子:codejava.net/frameworks/spring/… 或者只是一个带有 sessionFactory 的 applicationContext:alvinalexander.com/java/jwarehouse/spring-framework-2.5.3/…
猜你喜欢
  • 2014-01-25
  • 2013-09-14
  • 2011-07-05
  • 2015-06-23
  • 1970-01-01
  • 2011-11-17
  • 1970-01-01
  • 2019-05-29
  • 2012-01-11
相关资源
最近更新 更多