NULL_8757512 2008-08-08 17:51
浏览 673
已采纳

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没有运行完成之前 事物是一直打开的

我说的对么?

  • 写回答

2条回答 默认 最新

  • iteye_14762 2008-08-09 02:28
    关注

    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)不在事务中, 同样也会出错吧!哈哈!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)