1

Spring、Hibernate、MySQLを使用してアプリケーションを開発しています。テーブルの1つにDAOを作成しました。それでは、DAOのメソッド(保存、検索など)をテストしたいと思います。問題は、これらのメソッドがデータベースデータに影響を与えることです。そのため、特定のメソッドの実行後にすべての変更をロールバックしたいと思います。で設定defaultRollback=trueしてみまし@TransactionConfigurationたが、うまくいきません。以下に、コードの最も重要なフラグメントを貼り付けます。各メソッドの後にロールバックを強制する方法を知っている人はいますか?

MySQLの私のテーブルはInnoDBエンジンを使用しています。実際、テスト実行コンソールにはこの情報が含まれて INFO: Rolled back transaction after test execution for test context ...いますが、データベースの変更はコミットされます。

UsersDAOTest

@ContextConfiguration(locations={"classpath:applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
@Transactional
public class UsersDAOTest {

    @Autowired
    UsersHibernateDAO usersDAO;

    @Test
    public void test1() {
        List<Users> results = usersDAO.findAll();
        Assert.assertEquals(0, results.size());
    }

    @Test
    public void test2() {
        Users user = new Users("mchrobok", "12345678901234567890123456789012");
        usersDAO.saveOrUpdate(user);
        List<Users> results = usersDAO.findAll();
        Assert.assertEquals(1, results.size());     
    }   
}    

Hibernate(hibernate.cfg.xml)

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>    
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">create-drop</property>

        <mapping class="pl.fp.microblog.domain.Users"/>
    </session-factory>
</hibernate-configuration>

Spring構成(applicationContext.xml)

<beans>
     <context:component-scan base-package="pl.fp.microblog" />
     <tx:annotation-driven />

     <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"    destroy-method="close">
         <beans:property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <beans:property name="url" value="jdbc:mysql://localhost:3306/Microblog"/>
         <beans:property name="username" value="root"/>
         <beans:property name="password" value="root"/>
     </beans:bean>

     <beans:bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
     <beans:property name="dataSource" ref="dataSource" />
         <beans:property name="configLocation">
             <beans:value>
                 hibernate.cfg.xml
         </beans:value>
         </beans:property>
     </beans:bean>

     <beans:bean id="transactionManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
         <beans:property name="sessionFactory" ref="sessionFactory" />
     </beans:bean>

     <beans:bean name="usersDAO" class="pl.fp.microblog.dao.UsersHibernateDAO">
         <beans:property name="sessionFactory" ref="sessionFactory" />
     </beans:bean>
</beans:beans>

編集

UsersDAO(一般的ですが、問題ではありません)

public class GenericHibernateDAO<T> implements GenericDAO<T> {
    private SessionFactory sessionFactory;
    private Class<?> persistClass;

    public GenericHibernateDAO() {
        ParameterizedType type = ((ParameterizedType)getClass().getGenericSuperclass());
        persistClass = ((Class<?>) type.getActualTypeArguments()[0]);
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public List<T> findAll() {
        Criteria criteria = sessionFactory.openSession().createCriteria(persistClass);
        return criteria.list();
    }

    @Override
    public void saveOrUpdate(T entity) {
        sessionFactory.openSession().saveOrUpdate(entity);
    }
}
4

1 に答える 1

4

Hibernateコードで新しいセッションを開いているので、代わりにgetCurrentSession()を使用する必要があります。

コードの問題は、DAOクラスが独自にトランザクションを管理しようとすることです。最新のSpringアプリケーションでは、トランザクション管理はサービス層で実行する必要があります。

つまり、通常、サービスメソッドには。という注釈を付ける必要があります@Transactional

于 2012-12-08T21:56:59.233 に答える