1 零丁应用hibernate处理惩罚事物
底本只用hibernate开辟,从而可以省了DAO层实现数据库接见和跨数据库,也可以对代码进行更好的封装,当我们web中零丁应用hibernate时,我们须要零丁的处理惩罚hibernate的事务,我是应用filter来对事务进行把握的:
零丁应用hibernate应用filter进行事务把握:
HibernateSessionFilter.java
public class HibernateSessionFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Session session = HibernateUtils.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); chain.doFilter(request, response); tx.commit(); } catch (Exception e) { if (tx != null) { tx.rollback(); } throw new RuntimeException(e); } finally { HibernateUtils.closeAndRemoveSession(); } } public void init(FilterConfig arg0) throws ServletException { } }
web.xml
<filter> <filter-name>hibernateSessionFilter</filter-name> <filter-class> syx.jpkc.filter.HibernateSessionFilter</filter-class> </filter> <filter-mapping> <filter-name>hibernateSessionFilter</filter-name> <url-pattern>*.syx</url-pattern> <url-pattern>*.jsp</url-pattern> <url-pattern>*.eve</url-pattern> </filter-mapping>
&#160;
我首要在servlet(*.syx,*.eve)和jsp页面(没用struts)须要和数据库操纵,所以须要应用事务处理惩罚。
上方我们还用到了一个 HibernateUtils的小对象类,首要为了获取Session对象和一点优化:
HibernateUitls.java
public class HibernateUtils { private static Map<Thread, Session> sessionMap; private static SessionFactory sessionFactory; static { sessionMap = new HashMap<Thread, Session>(); sessionFactory = new Configuration().configure().buildSessionFactory(); } /** * can only use in web filter, beause it should remove and clear resources * @return */ public static Session openSession() { System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date()); Session session = sessionMap.get(Thread.currentThread()); if (session == null) { session = sessionFactory.openSession(); sessionMap.put(Thread.currentThread(), session); } return session; } public static Session getCurrentSession() { return sessionMap.get(Thread.currentThread()); } public static void closeAndRemoveSession() { System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());// Session session = sessionMap.remove(Thread.currentThread()); if (session != null) { session.close(); } } }
&#160;
2 hibernate整合进spring后的事物处理惩罚
spring事物处理惩罚的体式格式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
介绍常用的:
spring annotation声明式的事务经管
1) 事物处理惩罚层?
比如保存一个User,可以在Service层和DAOImpl层实现:
public void save(User u) { userDAO.save(u); } public void save(User u) { System.out.println("save user :" + this); Session s = sessionFactory.openSession(); s.beginTransaction(); s.save(u); s.getTransaction().commit(); s.close(); }
假如我们还有个日记记录,没保存一个User对象,要写入日记进入数据库。
而save(log) 和 save(user)必须处在同一事务中,所以不克不及放在DAOImpl层,事务处理惩罚在Service层。
2) 一般的事务处理惩罚
Session sess = factory.openSession(); Transaction tx; try { tx = sess.beginTransaction(); //do some work //save(user); //save(log); ... tx.commit(); } catch (Exception e) { if (tx!=null) tx.rollback(); throw e; } finally { sess.close(); }
并且要在实现层中的save()办法中也要参加事务处理惩罚,若是出呈现异常要throws给上级处理惩罚!
并且实现层中的session必须应用openCurrentSession()获得。
Session s = sessionFactory.getCurrentSession(); s.save(u);
3) spring annotation事务处理惩罚
Beans.xml中引入响应的xml定名空间和响应设备:
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd <tx:annotation-driven transaction-manager="txManager"/> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="¥{jdbc.driverClassName}" /> <property name="url" value="¥{jdbc.url}" /> <property name="username" value="¥{jdbc.username}" /> <property name="password" value="¥{jdbc.password}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.syx.model.User</value> <value>com.syx.model.Log</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="current_session_context_class">thread</prop> </props> </property> </bean> Save办法: public void save(User u) { Session s = sessionFactory.getCurrentSession(); s.save(u); } public void save(Log log) { Session s = sessionFactory.getCurrentSession(); s.save(log); } Service层处理惩罚: @Component("userService") public class UserService { UserDAO userDAO = null; LogDAO logDAO = null; public LogDAO getLogDAO() { return logDAO; } @Resource(name="logDAOMySQLImpl") public void setLogDAO(LogDAO logDAO) { this.logDAO = logDAO; } @Transactional public void save(User u) { userDAO.save(u); Log log = new Log(); log.setMsg(u.getName() + " saved in " + new Date()); logDAO.save(log); } public UserDAO getUserDAO() { return userDAO; } @Resource(name="userDAOMySQLImpl") public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }
4) @Transactional详解
什么时辰rollback
运行期异常,非运行期异常不会触发rollback
必须uncheck (没有catch)
不管什么异常,只要你catch了,spring就会放弃经管
事务传播特点:propagation_required
propagation 默认是 REQUIRED ,意思是有我们就用现成的,没的我们就发明一个,其他具体见文档
spring xml声明式的事务经管
设备景象和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中参加如下设备:
<!-- spring tranception xml config --> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com.syx.service..*.*(..))" /> <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="getUser" read-only="true" /> <tx:method name="save" /><!-- 相当于在上方切面pointcut@Transactional结果 --> </tx:attributes> </tx:advice>
3 hibernateTemplate.getSessionFactory().getCurrentSession()
我们应用spring和hibernate连络,操纵数据库最常用可能是HibernateTemplate,HibernateTemplate中集成了很多应用的办法,可惜的是没的createQuery办法,也许我们应用hibernate的时辰喜好应用Query,我们可能会封装hibernateTemplate.getSessionFactory().getCurrentSession()办法获得Session,session创建Query,这是一个办法,但你应当会获得异常 “createQuery without an active transaction”,因为应用hibernateTemplate.getSessionFactory().getCurrentSession(),你是应用的hibernate的事务经管,而你指望spring经管的事物是hibernateTemplate,所以你会提示没有打开事务的异常,解决办法:1)应用hibernate事务处理惩罚,就像上方零丁应用hibernate一样,但这也许不是你想要的。2)应用hibernateTemplate的HibernateCallBack回调:
return hibernateTemplate.executeWithNativeSession( new HibernateCallback<List<T>>() { public List<T> doInHibernate(Session session) throws HibernateException, SQLException { return session.createQuery ("FROM " + entityClass.getName() + " WHERE id IN (:ids)")// .setParameterList("ids", idList).list(); }
&#160;
实际上hibernateTemplate中封装的find办法也很强大,若是谙练应用完全可以调换createQuery的。
备注:
若是呈现异常:对同一个凑集处理惩罚不克不及应用2个session,这是因为getCurrentSession办法失足,导致打开一个新的session,搜检设备文件,若是应用tomcat+spring+hibernate 设备hibernate.current_session_context_class 最好为thread,固然支撑jta,设备斗劲麻烦,并且jta支撑多个sessionFactory,即可以跨数据库,斗劲强大!
若是hibernate+spring呈现session没有提友情况,应当是你让spring负责事务处理惩罚,而你有应用了hibernate的session,从而离开spring事务处理惩罚,即没的begintransaction和commit之类的操纵了。