2007-04-11
使用Spring AbstractTransactionalDataSourceSpringContextTests测试
关键字: AbstractTransactionalDataSourceSpringContextTests
在使用AbstractTransactionalDataSourceSpringContextTests这个作为测试hibernate的Service时,遇到这样的一个问题。 就是一定要在代码中显示的调用session.flush()。 更改操作才能立即看到。。
比如
如果我不在getBillingEntityService().deleteBillingEntity(1) 方法里面调用sesson.flush()的话。 这个测试是失败的。但是在真是环境中的话不调用session.flush()是能行的。Hibernate 默认的是autoFlush 大家应该也遇到相同的问题吧。 是如何解决的?
谢谢
比如
public void testDeleteBillingEntity(){
getBillingEntityService().deleteBillingEntity(1);
assertEquals("BillingEntity(1) should be not existed", getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BILLING_ENTITY WHERE ID=1"), 0);
}
如果我不在getBillingEntityService().deleteBillingEntity(1) 方法里面调用sesson.flush()的话。 这个测试是失败的。但是在真是环境中的话不调用session.flush()是能行的。Hibernate 默认的是autoFlush 大家应该也遇到相同的问题吧。 是如何解决的?
谢谢
评论
dengyin2000
2007-05-15
zhour560 写道
我也遇到Spring AbstractTransactionalDataSourceSpringContextTests测试不可以回滚的问题。数据库是MYSQL。在测试里面新增记录的时候,竟然加数据库里面去了。而且更新和删除都可以回滚的!
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;
public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);
sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}
protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
"file:web/WEB-INF/test-ApplicationContext*.xml"};
}
protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
sessionFactory.getCurrentSession().flush();
}
}
这是我测试基类。
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;
public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);
sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}
protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
"file:web/WEB-INF/test-ApplicationContext*.xml"};
}
protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
sessionFactory.getCurrentSession().flush();
}
}
这是我测试基类。
看看你mysql数据库是什么类型的。 ISM类型的应该不能回滚,因为不支持事务。 换成innodb
zhour560
2007-05-15
我也遇到Spring AbstractTransactionalDataSourceSpringContextTests测试不可以回滚的问题。数据库是MYSQL。在测试里面新增记录的时候,竟然加数据库里面去了。而且更新和删除都可以回滚的!
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;
public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);
sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}
protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
"file:web/WEB-INF/test-ApplicationContext*.xml"};
}
protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
sessionFactory.getCurrentSession().flush();
}
}
这是我测试基类。
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;
public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);
sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}
protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
"file:web/WEB-INF/test-ApplicationContext*.xml"};
}
protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
sessionFactory.getCurrentSession().flush();
}
}
这是我测试基类。
dengyin2000
2007-05-11
用session.get试试
晨星★~雨泪
2007-05-11
我总觉得既然已删除 那么查出的结果应为NULL 才对,为什么要报错?
如果我 用 Hibernate findByid 去查一个数据表里没有的记录 那不是老抛异常.
如果我 用 Hibernate findByid 去查一个数据表里没有的记录 那不是老抛异常.
spiritfrog
2007-05-10
晨星★~雨泪 写道
我用 Hibernate delete 后 用Spring JdbcTemplate 查被删的记录还是存在,可用 Hibernate findByid 就会报 该记录已删 的错误.郁闷
hibernate delete只是在缓存中将某个持久对象给标记成删除的,但没有flunsh就实际没有执行删除操作,而JdbcTemplate不在session控制之下,因此还能从数据库找到标记为删除的记录。当然,被标记为删除的记录,再次通过hibernate来查找就会抛出异常,说已经被删除了。
spiritfrog
2007-05-10
这里是需要调用session的flunsh的,因为getJdbcTemplate().queryForInt方法不会flunsh缓存。
晨星★~雨泪
2007-05-10
我用 Hibernate delete 后 用Spring JdbcTemplate 查被删的记录还是存在,可用 Hibernate findByid 就会报 该记录已删 的错误.郁闷
温柔一刀
2007-04-14
dada 写道
我不认为测试一定要直接操作数据库,尤其是用hibernate的时候。
如果用了hibernate
测试的时候用hsqldb就可以了
dada
2007-04-11
dengyin2000 写道
刚刚看了下,确实是拿的session cache中的对象, 根本没有发送select 语句
这段代码的本意就是判断session中的对象是否被删除了。
前头漏了段
public void testDelete() {
Sample sample = dao.get(new Long(1));
dao.delete(sample);
Object obj = dao.get(new Long(1));
AssertNull(obj);
}
我不认为测试一定要直接操作数据库,尤其是用hibernate的时候。
dengyin2000
2007-04-11
刚刚看了下,确实是拿的session cache中的对象, 根本没有发送select 语句
dengyin2000
2007-04-11
dada 写道
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
protected SessionFactory getSessionFactory(){
return (SessionFactory) getApplicationContext().getBean("sessionFactory");
}
protected void flushCurrentSession(){
Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
if (session !=null){
session.flush();
}
}我觉得改变测试方法比较好:
public void testDelete() {
service.delete(new Long(1));
Object obj = service.get(new Long(1));
assertNull(obj);
}
刚刚又想到了你这样会不会有问题。看下面的代码,我把delete变成了save
public void testSave() {
service.save(new Long(1));
Object obj = service.get(new Long(1));
assertNull(obj);
}
因为在testSave中是在一个session中, 所以service.get的话可能根本不会读数据库里面的值, 而是拿的session cache中的?
dengyin2000
2007-04-11
Godlikeme 写道
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession
这个问题我看错了,原来问题是jdbctemplate.execute(),不是不同session的问题。
只能显示调用sessionFlush了,hibernateTemplate和jdbcTemplate一块用,这样不一致性的问题就会一直存在。
是的 我没有发现,hibernateTemplate有executeWithSession这个方法。
正规的话 当然是应该用jdbc来测试的。
Godlikeme
2007-04-11
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession
这个问题我看错了,原来问题是jdbctemplate.execute(),不是不同session的问题。
只能显示调用sessionFlush了,hibernateTemplate和jdbcTemplate一块用,这样不一致性的问题就会一直存在。
Godlikeme
2007-04-11
tsingn 写道
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession
同意!
但是不知道为什么用不同的session flush一下也会起作用?
flush后session是与数据库同步的,因为测试不是多线程,session之间就不会出现不一致的情况。
dengyin2000
2007-04-11
dada 写道
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
protected SessionFactory getSessionFactory(){
return (SessionFactory) getApplicationContext().getBean("sessionFactory");
}
protected void flushCurrentSession(){
Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
if (session !=null){
session.flush();
}
}我觉得改变测试方法比较好:
public void testDelete() {
service.delete(new Long(1));
Object obj = service.get(new Long(1));
assertNull(obj);
}
我有遇到你这种情况, 一个同事使用jdbc去验证的时候 会有问题, 但是我用service去拿的话 就能通过。 最后发现我这里发送了update语句,而用jdbc去验证的话并没有flush。 我不觉得你上面的方式好。 因为我这种方式对于使用jdbc或者其他方式去验证都是有效的, 而且如果我没有get find方法呢? 我还要为测试去加多这样的方法?
dada
2007-04-11
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
protected SessionFactory getSessionFactory(){
return (SessionFactory) getApplicationContext().getBean("sessionFactory");
}
protected void flushCurrentSession(){
Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
if (session !=null){
session.flush();
}
}我觉得改变测试方法比较好:
public void testDelete() {
service.delete(new Long(1));
Object obj = service.get(new Long(1));
assertNull(obj);
}
tsingn
2007-04-11
AbstractTransactionalDataSourceSpringContextTests里面的tearDown有两个方法:onTearDownInTransaction和onTearDownAfterTransaction
所以你可以试着把flush的操作放在onTearDownInTransaction里面看看,这样你不用每次都要在测试方法里面调用了!
完了把测试结果贴一下,呵呵。
所以你可以试着把flush的操作放在onTearDownInTransaction里面看看,这样你不用每次都要在测试方法里面调用了!
完了把测试结果贴一下,呵呵。
dengyin2000
2007-04-11
总结下, 应该commit transaction才会触发session 的flush的吧。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。
想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。
protected SessionFactory getSessionFactory(){
return (SessionFactory) getApplicationContext().getBean("sessionFactory");
}
protected void flushCurrentSession(){
Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
if (session !=null){
session.flush();
}
}
tsingn
2007-04-11
dada 写道
一个测试方法一个transaction,assertEquals这里session还没有关闭,所以你测试不会通过。
这样说就能够解释了,我一直以为session在dao.delete()方法结束后就关闭了。哈哈
dada
2007-04-11
一个测试方法一个transaction,assertEquals这里session还没有关闭,所以你测试不会通过。
- 浏览: 220248 次
- 性别:

- 来自: 广州

- 详细资料
搜索本博客
我的相册
VB-seamless
共 13 张
共 13 张
最近加入圈子
最新评论
-
使用Terracotta和Tomcat建 ...
renavatior 写道"运行start.bat 9081 这样我们就启动了目 ...
-- by rainsf -
使用Terracotta和Tomcat建 ...
"运行start.bat 9081 这样我们就启动了目录9081中的tomcat ...
-- by renavatior -
广州3年多经验 5500的 ...
fucku 写道广州的软件厂家可比深圳多多了,不过比起北京上海来,还是少了很多, ...
-- by yongfan_420 -
广州3年多经验 5500的 ...
广州的软件厂家可比深圳多多了,不过比起北京上海来,还是少了很多,导致机会也没有这 ...
-- by fucku -
广州3年多经验 5500的 ...
想高工资就去厂家咯,老在集成商里面混能有多大个奔头
-- by fucku






评论排行榜