HibernateTemplate 在事务、非事务、配置OpenSessionInViewFilter等不同情况下获取Session

HibernateTemplate在事务、非事务、配置OpenSessionInViewFilter等不同情况获取Session,总结如下:

    1、事务在Controller处配置即可,一般情况无需在业务类中配置事务,除非业务类有不同的事务传播行为或隔离级别。

    2、从定义了事务的方法为入口,方法里树形调用的方法(无论是否配置了事务)都在同一事务里。

    3、同一事务下的方法使用同一Session。

    4、在同一session下,相同Id的对象只有一个实例。

    5、对象的持久态只在同一的session中有效。

    6、配置了OpenSessionInViewFilter,同一连接使用同一Session,如果无事务,此Session为readonly,需手动设置session.setFlushMode(FlushMode.AUTO); 才能进行增删改。

具体实例应用了业务类SpringHibernateEmployeeScroll和Controller类EmployeeManageController,具体代码如下

@Named("springHibernateEmployeeScroll")
<a>@Transactional</a>                              ①
public class SpringHibernateEmployeeScroll implements EmployeeScroll {

	@Resource(name="hibernateTemplate")
	HibernateTemplate hibernateTemplate;

	@Override
	public void enroll(Employee employee) { 
		Session session  = hibernateTemplate.getSessionFactory().getCurrentSession();
		System.out.print("enroll:session"+session.toString());
		hibernateTemplate.save(employee);	
	}

	@Override
	public Employee get(Object id) {
		Session session  = hibernateTemplate.getSessionFactory().getCurrentSession();
		Employee employee = (Employee) session.get(Employee.class, (Serializable) id);	
		System.out.print("get:session"+session.toString());
		return employee; 		
	}

	@Override
	public Object getIdentifier(Employee employee) { 
		Object id=null; 
		Session session  = hibernateTemplate.getSessionFactory().getCurrentSession(); 
	    id=session.getIdentifier(employee); 
	    System.out.print("getIdentifier:session"+session.toString());
		return id;
	}
}


@Controller
<a>@Transactional</a>                          ②
@RequestMapping("/hr")
public class EmployeeManageController {
		
	@Resource(name="springHibernateEmployeeScroll")
	EmployeeScroll employeeScroll;
	
	
	@RequestMapping("/employeeeditshow")
	public String employeeEdit(Model model){	
		int code=(int) Math.round(Math.random() * (999999 - 100000) + 100000);		
		model.addAttribute("employeeCode", code);	
		model.addAttribute("employeeId","");
		return "hr/employeeEdit";
	}
	
	@RequestMapping("/employeeeditSave")
	public String employeeSave(Model model,Employee employee){
		
			employeeScroll.enroll(employee);                 ③
			Employee employeeMessage=employeeScroll.get(1);	 ④
			employeeMessage=employeeScroll.get(1);           ⑤
			employeeMessage=employeeScroll.get(2);	         ⑥
			id=employeeScroll.getIdentifier(employee);       ⑦			
			employeeMessage=employeeScroll.get(id);          ⑧
		
		model.addAttribute("employeeId", id);
		model.addAttribute("employee", employeeMessage); 
		return "hr/employeeDetail";
       }
}


OpenSessionInViewFilter在web.xml的配置:


 <filter>
		<filter-name>hibernateSessionFilter</filter-name>
		<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>hibernateSessionFilter</filter-name>
		<url-pattern>*.do</url-pattern>
	</filter-mapping>


具体验证过程与结果(通过单点调试模式,查看对象的内存地址,断点在每个方法的返回操作处):

1、在事务下,同时在web.xml配置OpenSessionInViewFilter

      前置条件:1)①②不注释掉 ;    2) Web.xml不配置OpenSessionInViewFilter

步骤Employee/(内存地址)SessionImpl(内存地址)说明
③enrollEmployee(id=132)
SessionImpl(id=133)

④get(1)Employee(id=134)
SessionImpl(id=133)

⑤get(1)Employee(id=134)
SessionImpl(id=133)

⑥get(2)Employee(id=137)
SessionImpl(id=133)

⑦getIdentifierEmployee(id=132)
SessionImpl(id=133)

⑧get(id)Employee(id=132)
SessionImpl(id=133)

        结论:1)同一事务下的方法都使用同一Session对象
                   2)在同一session下,相同Id的对象只有一个实例


2、业务类对象在事务下,Controller(Action)类对象不在事务下,在web.xml配置OpenSessionInViewFilter

      前置条件:1)①不注释掉,②注释掉 ;    2) Web.xml不配置OpenSessionInViewFilter

步骤Employee(内存地址)SessionImpl(内存地址)说明
③enrollEmployee(id=80)
SessionImpl(id=82)

④get(1)Employee(id=106)
SessionImpl(id=105)

⑤get(1)Employee(id=112)
SessionImpl(id=111)

⑥get(2)Employee(id=116)
SessionImpl(id=115)

⑦getIdentifier

报错:org.hibernate.TransientObjectException: The instance was not associated with this session
⑧get(id)


        结论:1)Controller不配置事务,业务类在事务下的方法都分别使用不同的session
                   2)对象的持久态只在同一的session中有效

3、业务类对象事务下,Controller(Action)类对象在事务下,在web.xml配置OpenSessionInViewFilter

      前置条件:1)①注释掉,②不注释掉 ;    2) Web.xml不配置OpenSessionInViewFilter

步骤Employee(内存地址)SessionImpl(内存地址)说明
③enrollEmployee(id=82)
SessionImpl(id=87)

④get(1)Employee(id=107)
SessionImpl(id=87)

⑤get(1)Employee(id=107)
SessionImpl(id=87)

⑥get(2)Employee(id=109)
SessionImpl(id=87)

⑦getIdentifierEmployee(id=82)
SessionImpl(id=87)

⑧get(id)Employee(id=82)
SessionImpl(id=87)

        结论:1)与检验过程1的结果相同,
                   2)在Controller处配置事务即可,一般情况无需在业务类中配置事务,除非业务类有不同的事务传播行为或隔离级别

4、业务类对象在事务下,Controller(Action)类对象不在事务下,在web.xml配置OpenSessionInViewFilter

      前置条件:1)①不注释掉,②注释掉  ;    2) Web.xml配置OpenSessionInViewFilter

步骤Employee(内存地址)SessionImpl(内存地址)说明
③enrollEmployee(id=82)
SessionImpl(id=84)

④get(1)Employee(id=109)
SessionImpl(id=84)

⑤get(1)Employee(id=109)
SessionImpl(id=84)

⑥get(2)Employee(id=116)
SessionImpl(id=84)

⑦getIdentifierEmployee(id=82)
SessionImpl(id=84)

⑧get(id)Employee(id=82)
SessionImpl(id=84)

        结论:1)与检验过程1、3的结果相同,
                   2)配置了OpenSessionInViewFilter,一个连接都共用一个session
                   3)由于业务对象设置的事务,所以进行save时,没有像检验过程6那样报错


5、在事务下,同时在Web.xml配置OpenSessionInViewFilter

       前置条件:1) ①②都注释掉 ;    2) Web.xml不配置OpenSessionInViewFilter

步骤Employee(内存地址)SessionImpl(内存地址)说明
③enroll

执行getCurrentSession报错误:org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
④get(1)


⑤get(1)


⑥get(2)


⑦getIdentifier


⑧get(id)


        结论:getCurrentSession获取的是事务下ThreadLocal的Session,所以在非事务下,会报错

6、在非事务下,同时在web.xml配置OpenSessionInViewFilter

      前置条件:1)①②都注释掉 ;    2) Web.xml配置OpenSessionInViewFilter

步骤Employee(内存地址)SessionImpl(内存地址)说明
③enroll

执行save报错误:org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL):
④get(1)


⑤get(1)


⑥get(2)


⑦getIdentifier


⑧get(id)


        结论:OpenSessionInViewFilter在非事务下,设置Session的FlushMode.NEVER(ReadOnly),所以会报以上错。如果希望在非事务下进行save、updat、delete,则需要对Session手动设置FlushMode.AUTO
                Session session  = hibernateTemplate.getSessionFactory().getCurrentSession();
                session.setFlushMode(FlushMode.AUTO); 
       此文对OpenSessionInViewFilter讲解比较透彻:http://blog.sina.com.cn/s/blog_5dc12c490100crr5.html





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值