[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加载.