Spring事务何时关闭

[code="xml"]
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">


class="com.downloadmanage.service.impl.DiscServiceImpl">





PROPAGATION_REQUIRED,readOnly
PROPAGATION_REQUIRED



[/code]

在applicationContext.xml中我给DiscService设置了事物

Disc和Game是one-to-many的关系,Game端为lazy加载

我在Junit里面有这样一个测试:
[code="java"]
/**
* 测试:输出找到的Disc的DiscNumber以检测延迟加载的情况
*/
public void testAddGameForDisc(){
try {
Disc disc = discService.findDiscByDiscNumber("M16");
System.out.println("找到这张盘,光盘的编号是: "+disc.getDiscNumber());
System.out.println("光盘内游戏有: "+disc.getGames().iterator().next().getGameName());
} catch (NotFoundInDBException e) {
System.out.println("没有这张光盘");
}
}
[/code]

控制台给我的结果是:

Hibernate: select disc0_.disc_id as disc1_1_, disc0_.borrow_to as borrow2_1_, disc0_.disc_number as disc3_1_, disc0_.save_place as save4_1_ from downloadmanage.disc disc0_ where disc0_.disc_number=?
找到这张盘,光盘的编号是: M16
Hibernate: select games0_.game_in as game2_1_, games0_.game_id as game1_1_, games0_.game_id as game1_4_0_, games0_.game_in as game2_4_0_, games0_.game_type as game3_4_0_, games0_.game_name as game4_4_0_ from downloadmanage.game games0_ where games0_.game_in=?
光盘内游戏有: Diablo

也就是说Game类的确被lazy加载了,不过我预期的结果是

System.out.println("光盘内游戏有: "+disc.getGames().iterator().next

这个语句会报错,也即是说 他不应该再向数据库查询了。

我没有配置SessionInView模式,那怎么还会出现这种情况呢?

谢谢

[b]问题补充:[/b]
那请问一下 这个Session什么时候才关闭呢?

我已经调用完DiscServie 及从数据库库中读到这个Disc了,剩下的工作就是操作

这个未被完全初始化的Disc的业务操作了。和底层数据库没有关系了。

所以我想调用完

Disc disc = discService.findDiscByDiscNumber("M16");

就关闭Session 请问应该怎么写呢 ?

我的DAO层是直接用的Spring之中的getHibernateTemplate() 等于

是不是应该可以说Spring把Session的事情给我屏蔽掉了?

谢谢您的回答。

[b]问题补充:[/b]
我可能自己找到答案了,不过还是要您给看看我说得对不对。

当整个test工作在

public class DiscServiceImplTest extends
AbstractDependencyInjectionSpringContextTests {

模式下,效果和我想象的是一样的。

并且当test工作在

public class DiscServiceImplTest extends
AbstractTransactionalSpringContextTests {

整个模式下,但是我

System.out.println("找到这张盘,光盘的编号是: "+disc.getDiscNumber());
        endTransaction();
        System.out.println("光盘内游戏有: "+disc.getGames().iterator().next().getGameName());

手工调用了endTransaction();

也达到了相应目的。

也就是说其实DiscService的事物已经完成了,不过由于整个test具有事务性,通过事物的传递,所以当test没有运行完成之前 事物是一直打开的

我说的对么?

1, lz理解是正确的.每个AbstractTransactionalSpringContextTests中的test方法确实是被自动的添加在事务里面了!而且默认情况下, 这个被添加的事务还是[readOnly = false], 也就是说, 就算你的discService不加事务, 你的save(), saveOrUpdate()操作也是可以执行的.但是如果Override下面这个方法:
[code="java"]@Override
protected void onSetUp() throws Exception {
DefaultTransactionDefinition td = (DefaultTransactionDefinition) transactionDefinition;
td.setReadOnly(true);
super.onSetUp();
}[/code]
, 就会抛错:
[code="java"]org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.......[/code], 这也算是AbstractTransactionalSpringContextTests的一个magic吧
2, 如果lz没有配置SessionInView模式, 那么在jsp页面中使用jstl读取disc的games的数据的时候, 就会出错, 因为这时session已经关掉了!想想, 如果你的Action(或Controller)不在事务中, 同样也会出错吧!哈哈!

这个和Spring事务没有关系.
Hibernate中,从session中得到的对象是被代理过的,当lazy加载的时候,调用这个对象的一个方法就会lazy载入数据. 应该没有问题的.
你这样测试反而是证明了Hibernate的Lazy加载.