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

原文地址:https://www.cnblogs.com/yaowen/p/2933102.html