过滤器之Hibernate自动提交事务,并关闭会话
来源:互联网 发布:谷歌人工智能产品 编辑:程序博客网 时间:2024/06/08 23:50
最近我们学到的Hibernate中,有个对房屋信息的查询功能。其中页面的一句代码如下:
${house.street.district.name}区${house.street.name},${house.floorage}平米<br /> 联系方式:${house.contact}
以上写法用EL显示房屋的信息,但我们的DAO用Hibernate实现的时候,几个相关的对象都要把lazy设置成false,不然就会出现会话已经关闭的错误。以下是House.hbm.xml原来的写法:
<many-to-one name="users" class="org.newboy.entity.Users" fetch="join" lazy="false"> <column name="USER_ID" precision="7" scale="0" /> </many-to-one> <many-to-one name="houseType" class="org.newboy.entity.HouseType" fetch="select" lazy="false"> <column name="TYPE_ID" precision="4" scale="0" /> </many-to-one> <many-to-one name="street" class="org.newboy.entity.Street" fetch="join" lazy="false"> <column name="STREET_ID" precision="6" scale="0" /> </many-to-one>
因为在访问到house.street的时候,Hibernate还会再去查一次数据库,而如果我们的DAO中的代码如下:
@SuppressWarnings("unchecked")public List<House> getAllHouses() {Session session = super.getSession();List<House> houses = null;try {houses = session.createQuery("from House").list();} finally {session.close();}return houses;}
会话已经关闭,就会出现会话关闭的错误。当然还有一种做法就是不关闭会话,不过这不是一种解决的办法。
虽然以后我们会学到Spring有更好的解决方法,但今天如果只用Hibernate的话,我们自己有没有办法去解决这个问题,就是让会话在请求结束后才关闭。这样也就不用把lazy设置成false了。于是就有了下面的过滤器的实现:
package org.newboy.servlet;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.apache.log4j.Logger;import org.hibernate.Session;import org.hibernate.Transaction;import org.newboy.utils.HibernateUtils;/** * 用于进行Hibernate事务处理的Servlet过滤器 * * @author LiuBo */public class HibernateFilter implements Filter {private static Logger log = Logger.getLogger(HibernateFilter.class);/** * 过滤器的主要方法 用于实现Hibernate事务的开始和提交 */public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {Session session = HibernateUtils.getSession();Transaction tx = session.beginTransaction();try {// 开始一个新的事务log.info("Starting a database transaction");tx.begin();log.info("Request Path:\t" + ((HttpServletRequest) request).getServletPath());// Call the next filter (continue request processing)chain.doFilter(request, response);// 提交事务log.info("Committing the database transaction");tx.commit();} catch (Throwable ex) {ex.printStackTrace();try {// 回滚事务log.info("Trying to rollback database transaction after exception");tx.rollback();} catch (Throwable rbEx) {log.error("Could not rollback transaction after exception!", rbEx);}// 抛出异常throw new ServletException(ex);} finally {log.info("session closed");HibernateUtils.closeSession();}}/** * Servlet过滤器的初始化方法 可以读取配置文件中设置的配置参数 */public void init(FilterConfig filterConfig) throws ServletException {}/** * Servlet的销毁方法 用于释放过滤器所申请的资源 */public void destroy() {}}
<filter><description>事务的过滤器</description><filter-name>HibernateFilter</filter-name><filter-class>org.newboy.servlet.HibernateFilter</filter-class></filter><filter-mapping><filter-name>HibernateFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
这样我们的DAO就可以这样写:
@SuppressWarnings("unchecked")public List<House> getAllHouses() {Session session = HibernateUtils.getSession();List<House> houses = session.createQuery("from House").list();return houses;}
不用关闭会话,而House.hbm.xml就变成:
<many-to-one name="users" class="org.newboy.entity.Users"> <column name="USER_ID" precision="7" scale="0" /> </many-to-one> <many-to-one name="houseType" class="org.newboy.entity.HouseType"> <column name="TYPE_ID" precision="4" scale="0" /> </many-to-one> <many-to-one name="street" class="org.newboy.entity.Street"> <column name="STREET_ID" precision="6" scale="0" /> </many-to-one>
没有了lazy那项。
其中HibernateUtils的代码基本上是MyEclipse自动产生的。只是我把它汉化了。呵呵:
package org.newboy.utils;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.cfg.Configuration;/** * 配置Hibernate工具,对会话工厂和会话进行操作 */public class HibernateUtils {private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();private static Configuration configuration = new Configuration();private static org.hibernate.SessionFactory sessionFactory;private static String configFile = CONFIG_FILE_LOCATION;static {try {configuration.configure(configFile);sessionFactory = configuration.buildSessionFactory();} catch (Exception e) {System.err.println("会话工厂创建失败");e.printStackTrace();}}/* * 私有的构造方法 */private HibernateUtils() {}/** * 得到一个线程安全的实例 * * @return Session * @throws HibernateException */public static Session getSession() throws HibernateException {Session session = (Session) threadLocal.get();if (session == null || !session.isOpen()) {if (sessionFactory == null) {rebuildSessionFactory();}session = (sessionFactory != null) ? sessionFactory.openSession() : null;threadLocal.set(session);}return session;}/** * 重新建立会话工厂 */public static void rebuildSessionFactory() {try {configuration.configure(configFile);sessionFactory = configuration.buildSessionFactory();} catch (Exception e) {System.err.println("会话工厂创建失败");e.printStackTrace();}}/** * 关闭单个会话实例. * * @throws HibernateException */public static void closeSession() throws HibernateException {Session session = (Session) threadLocal.get();threadLocal.set(null);if (session != null) {session.close();}}/** * 返回会话工厂实例 */public static org.hibernate.SessionFactory getSessionFactory() {return sessionFactory;}/** * 设置配置文件 */public static void setConfigFile(String configFile) {HibernateUtils.configFile = configFile;sessionFactory = null;}/** * 返回配置对象 */public static Configuration getConfiguration() {return configuration;}}
这样每次用户请求就会打开会话和事务,请求结束就提交事务,并关闭会话。解决了上面的问题。
- 过滤器之Hibernate自动提交事务,并关闭会话
- Hibernate Tip: 使用JBOSS MBEAN时,Session会在事务提交后自动关闭!
- Hibernate——ThreadLocal模式下管理的Session会在事务提交后自动关闭
- Spring事务 之 事务自动提交
- Spring事务之七(事务自动提交)
- HIBERNATE 事务提交
- Hibernate事务未提交
- Hibernate的事务提交
- 二、hibernate提交事务
- 自动提交事务
- 自动提交 与 事务
- Spring与Hibernate的整合,不配置事务管理器,事务会自动提交(Hibernate默认手动提交)
- Mysql 关闭自动提交
- postgresql关闭自动提交
- postgresql关闭自动提交
- Spring Hibernate 单元测试配置为事务自动回滚时需要提交事务时的处理
- Spring基础五之Springmvc和hibernate事务不提交
- ThreadLocal模式下管理的Session会在事务提交后自动关闭
- oracle异常错误处理
- 内核中_init,_exit中的作用
- hession的入门级使用方法
- [SQL]提升查询效率与避免LOCK发生
- HTML5 canvas 基础入门教程
- 过滤器之Hibernate自动提交事务,并关闭会话
- git-->进一步学习无网络情况下
- 类CL_ABAP_TYPEDESCR,动态取得运行时类型
- 栈和队列(二):栈的应用举例
- 今天温度比昨天还要高,晚上又要开空调睡了!
- iOS Dev Center Telephone Support
- 多媒体播放声音多路输出
- wince/WinForm下实现一个自动关闭的MessageBox
- HDU1271 整数对