不持久进行集成测试的实体(Hibernate + Spring Roo ActiveRecord)

时间:2014-01-19 15:41:05

标签: spring hibernate jpa junit4 spring-roo

经过多次麻烦,我来到这里寻求帮助。我无法从测试用例中将数据持久保存到开发数据库(以及嵌入式数据库)。当我在没有断言的情况下运行测试用例时,它没有任何异常。我使用Spring Roo生成的实体。使用相同的应用程序上下文配置,我可以从Spring控制器将数据保存到数据库中。所以我确信我的实体没有任何问题。

@TransactionConfiguration(defaultRollback=false)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/META-INF/spring/applicationContext.xml" })
@Transactional
public class UserServiceTest {

    @Rollback(false)
    @Test
    public void test() {
        Role role = new Role();
        role.setRolename("ROLE_ADMIN");
        // No Exception here on trying to persist
        role.persist();
        // Getting Exception here.. "No transaction is in progress"
        // role.flush();

        // Getting "No entity found for query exception"
        assertEquals(Role.findRolesByRolenameEquals("ROLE_ADMIN").getSingleResult().getRolename(), "ROLE_ADMIN");
    }
}

我的applicationContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd      
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd   
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        ">

    <context:property-placeholder location="classpath*:META-INF/spring/*.properties" />

    <context:spring-configured />

    <context:component-scan base-package="com.company">
        <context:exclude-filter expression=".*_Roo_.*"
            type="regex" />
        <context:exclude-filter expression="org.springframework.stereotype.Controller"
            type="annotation" />
    </context:component-scan>

    <bean class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" id="dataSource">
        <property name="driverClassName" value="${testDatabase.driverClassName}" />
        <property name="url" value="${testDatabase.url}" />
        <property name="username" value="${testDatabase.username}" />
        <property name="password" value="${testDatabase.password}" />
        <property name="testOnBorrow" value="true" />
        <property name="testOnReturn" value="true" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="1800000" />
        <property name="numTestsPerEvictionRun" value="3" />
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <property name="validationQuery" value="select 1 from INFORMATION_SCHEMA.TABLES" />
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager"
        id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven mode="aspectj"
        transaction-manager="transactionManager"  proxy-target-class="true" />
    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="persistenceUnitTest" />
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

My Persistence.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="persistenceUnitTest"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.company.domain.User</class>
        <class>com.company.domain.Role</class>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <property name="hibernate.hbm2ddl.auto" value="none" />
            <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy" />
            <property name="hibernate.connection.charSet" value="UTF-8" />
        </properties>
    </persistence-unit>
</persistence>

编辑:添加了持久性逻辑 我在Role_Roo_Jpa_ActiveRecord.aj中的持久性逻辑

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).

package com.company.domain;

import com.company.domain.Role;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;

privileged aspect Role_Roo_Jpa_ActiveRecord {

    @PersistenceContext
    transient EntityManager Role.entityManager;

    public static final EntityManager Role.entityManager() {
        EntityManager em = new Role().entityManager;
        if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
        return em;
    }

    public static long Role.countRoles() {
        return entityManager().createQuery("SELECT COUNT(o) FROM Role o", Long.class).getSingleResult();
    }

    public static List<Role> Role.findAllRoles() {
        return entityManager().createQuery("SELECT o FROM Role o", Role.class).getResultList();
    }

    public static Role Role.findRole(Integer roleId) {
        if (roleId == null) return null;
        return entityManager().find(Role.class, roleId);
    }

    public static List<Role> Role.findRoleEntries(int firstResult, int maxResults) {
        return entityManager().createQuery("SELECT o FROM Role o", Role.class).setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

    @Transactional
    public void Role.persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

    @Transactional
    public void Role.remove() {
        if (this.entityManager == null) this.entityManager = entityManager();
        if (this.entityManager.contains(this)) {
            this.entityManager.remove(this);
        } else {
            Role attached = Role.findRole(this.roleId);
            this.entityManager.remove(attached);
        }
    }

    @Transactional
    public void Role.flush() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.flush();
    }

    @Transactional
    public void Role.clear() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.clear();
    }

    @Transactional
    public Role Role.merge() {
        if (this.entityManager == null) this.entityManager = entityManager();
        Role merged = this.entityManager.merge(this);
        this.entityManager.flush();
        return merged;
    }

} 

我使用相同的代码尝试了MySql和Hsqldb数据库。但没有运气。

我还有另一个问题。在开发的情况下,我不必在persistence.xml中指定Role和User类。如果我没有在测试配置中指定它们,我会遇到异常。

4 个答案:

答案 0 :(得分:0)

Roo允许您根据需要多次配置持久性引擎,尝试使用persistence setup命令从Roo shell重新配置持久性设置

答案 1 :(得分:0)

在您applicationContext.xml的{​​{1}}中指定context:component-scan base-packagecom.campus,但您的实体位于com.company.domain

您是否在web mvc命令后更改了主程序包?

尝试像这样设置applicationContext.xml

<context:component-scan base-package="com.company">
    <context:exclude-filter expression=".*_Roo_.*"
        type="regex" />
    <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation" />
</context:component-scan>

此外,我认为您可以从class删除persistencie.xml代码。

答案 2 :(得分:0)

你需要在那里冲洗。在调用flush之前,不会执行insert语句。 并且findRolesByRolenameEquals方法无法读取您从hibernate会话中保存的对象,因为它使用查询来加载对象

如果你注释掉断言,并让测试结束,你应该能够看到db中的记录,因为当事务完成时应该发生刷新,是不是这样?

答案 3 :(得分:0)

我通过从applicationContext.xml中删除组件扫描来实现它。现在,我可以将数据从测试用例持久存储到数据库(包括MySql和Hsqldb)中。现在测试用例正在传递,数据可以在数据库中看到。

<context:component-scan base-package="com.company">
    <context:exclude-filter expression=".*_Roo_.*"
        type="regex" />
    <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation" />
</context:component-scan>

我仍然无法弄清楚为什么这解决了我的问题。我仍然在这里找到一个有效的解释。

我的另一个问题仍然存在。我不得不手动将角色和用户类放在persistence.xml中。