我进行集成测试时可能与hibernate有关(可能与事务有关)

时间:2014-08-05 06:20:00

标签: java spring hibernate junit

这是一个简单的项目。我创建的用于说明此问题:https://bitbucket.org/sharc/tadamlist

简介: 我有两个实体:TDList和TDTask(TDTask被映射到列表为ManyToOne

@ManyToOne(fetch = FetchType.EAGER)
private TDList list;

所以,当我删除列表时,我将TDTask中的 list 字段设置为null

TDListDAOImpl:

public void remove(int id) {
    Session session = sessionFactory.getCurrentSession();
    TDList tdList = (TDList) session.load(TDList.class, id);
    if(tdList != null){
        tdTaskDAO.changeList(tdList, null);
        session.delete(tdList);
    }
}

TDTaskDAOImpl:

public void changeList(TDList from, TDList to) {
    if(from == null) {
        Query query = sessionFactory.getCurrentSession().createQuery("update TDTask set list = :newList where list = null");
        query.setEntity("newList", to);
        query.executeUpdate();
    } else if(to == null) {
        Query query = sessionFactory.getCurrentSession().createQuery("update TDTask set list = null where list = :oldList");
        query.setEntity("oldList", from);
        query.executeUpdate();
    } else {
        Query query = sessionFactory.getCurrentSession().createQuery("update TDTask set list = :newList where list = :oldList");
        query.setEntity("oldList", from);
        query.setEntity("newList", to);
        query.executeUpdate();
    }
}

问题: 当我测试时,列表在TDTask中没有设置为null,但在测试之后它就像是必须的:

测试代码

public void deleteListTest(){
    TDList list = new TDList();
    list.setTitle("First test list");
    tdListDAO.put(list);

    TDTask task = new TDTask();
    task.setTask("Bla-bla-bla");
    task.setDone(false);
    task.setList(list);
    tdTaskDAO.put(task);

    task = tdTaskDAO.get(task.getId());
    System.out.println(task);

    tdListDAO.remove(list.getId());
    Assert.assertNull(tdListDAO.get(list.getId()));

    task = tdTaskDAO.get(task.getId());
    System.out.println(task);
    Assert.assertNull(task.getList());
}

测试日志

Hibernate: insert into TDList (title) values (?)
Hibernate: insert into TDTask (done, list_id, task) values (?, ?, ?)
Hibernate: select tdtask0_.id as id1_1_, tdtask0_.done as done2_1_, tdtask0_.list_id as list_id4_1_, tdtask0_.task as task3_1_ from TDTask tdtask0_ where tdtask0_.id=?
TDTask{id=2, task='Bla-bla-bla', done=false, list=TDList{id=2, title='First test list'}}
Hibernate: update TDTask set list_id=null where list_id=?
Hibernate: delete from TDList where id=?
Hibernate: select tdlist0_.id as id1_0_, tdlist0_.title as title2_0_ from TDList tdlist0_ where tdlist0_.id=?
Hibernate: select tdtask0_.id as id1_1_, tdtask0_.done as done2_1_, tdtask0_.list_id as list_id4_1_, tdtask0_.task as task3_1_ from TDTask tdtask0_ where tdtask0_.id=?
TDTask{id=2, task='Bla-bla-bla', done=false, list=TDList{id=2, title='First test list'}}

在测试后从DB中选择:

mysql> select * from TDTask;
+----+------+-------------+---------+
| id | done | task        | list_id |
+----+------+-------------+---------+
|  2 |      | Bla-bla-bla |    NULL |
+----+------+-------------+---------+

我的测试课程:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:*/BaseDAOImplTest-context.xml")
@TransactionConfiguration(defaultRollback = false)
@Transactional
public class TDListDAOImplTest {

    @Autowired
    TDListDAO tdListDAO;

    @Autowired
    TDTaskDAO tdTaskDAO;

    @Test
    public void deleteListTest(){
        TDList list = new TDList();
        list.setTitle("First test list");
        tdListDAO.put(list);

        TDTask task = new TDTask();
        task.setTask("Bla-bla-bla");
        task.setDone(false);
        task.setList(list);
        tdTaskDAO.put(task);

        task = tdTaskDAO.get(task.getId());
        System.out.println(task);

        tdListDAO.remove(list.getId());
        Assert.assertNull(tdListDAO.get(list.getId()));

        task = tdTaskDAO.get(task.getId());
        System.out.println(task);
        Assert.assertNull(task.getList());
    }

}

和配置:

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

    <context:component-scan base-package="tadamlist.core.dao"/>
    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager"/>

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

    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource"
          p:driverClassName="com.mysql.jdbc.Driver"
          p:url="jdbc:mysql://localhost:3306/tadamlist?useUnicode=true&amp;characterEncoding=utf8"
          p:username="tadamer"
          p:password="123456"/>

    <bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="tadamlist.core.model"/>
        <property name="annotatedPackages">
            <list>
                <value>tadamlist.core.model</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

</beans>

更新

如果我从其他事务中选择TDTask它有list = null,那么事务有问题,但为什么呢?休眠(或其他)在事务中以其他顺序执行操作吗?

1 个答案:

答案 0 :(得分:0)

问题是因为Hibernate L1缓存。