• Hibernate整合进spring


    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之类的操纵了。

  • 相关阅读:
    区块链解读
    如何在ASP.NET Core项目启动时执行异步定时任务
    深入理解ASP.NET Core中的Program类和Startup类
    VS 2017 .Net Core Error : 项目文件不完整,缺少预期导入。
    dotnet不是内部或外部的命令,也不是可运行的程序或批处理文件
    win10系统卸载matlab时出现exeption calling main怎么解决?
    解决mui错误:Unable to preventDefault inside passive event listener due to target being treated as passive.
    类型"*.Properties.Resources" 没有名为"*"的属性
    C#生成唯一不重复订单号帮助类
    Day16.参数传递(token传递,接口关联等)
  • 原文地址:https://www.cnblogs.com/yaowen/p/2933102.html
Copyright © 2020-2023  润新知