`
u011721609
  • 浏览: 45423 次
社区版块
存档分类
最新评论

Hibernate整合进spring--使用hibernateTemplate.getSessionFactory().getCurrentSession()理解

 
阅读更多

1 单独使用hibernate处理事务

本来只用hibernate开发,从而可以省了DAO层实现数据库访问和跨数据库,也可以对代码进行更好的封装,当我们web中单独使用hibernate时,我们需要单独的处理hibernate的事务,我是使用filter来对事务进行控制的:

单独使用hibernate使用filter进行事务控制:

HibernateSessionFilter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
publicclassHibernateSessionFilter implementsFilter {
publicvoiddestroy() {
}
publicvoiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain) throwsIOException,
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();
}
thrownewRuntimeException(e);
} finally{
HibernateUtils.closeAndRemoveSession();
}
}
publicvoidinit(FilterConfig arg0) throwsServletException {
}
}

web.xml

1
2
3
4
5
6
7
8
9
10
<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>

我主要在servlet(*.syx,*.eve)和jsp页面(没用struts)需要和数据库操作,所以需要使用事务处理。

上面我们还用到了一个 HibernateUtils的小工具类,主要为了获取Session对象和一点优化:

HibernateUitls.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
publicclassHibernateUtils {
privatestaticMap<Thread, Session> sessionMap;
privatestaticSessionFactory sessionFactory;
static{
sessionMap = newHashMap<Thread, Session>();
sessionFactory = newConfiguration().configure().buildSessionFactory();
}
/**
* can only use in web filter, beause it should remove and clear resources
* @return
*/
publicstaticSession openSession() {
System.out.println(Thread.currentThread().getStackTrace()[1] + " run in "+ newDate());
Session session = sessionMap.get(Thread.currentThread());
if(session == null) {
session = sessionFactory.openSession();
sessionMap.put(Thread.currentThread(), session);
}
returnsession;
}
publicstaticSession getCurrentSession() {
returnsessionMap.get(Thread.currentThread());
}
publicstaticvoidcloseAndRemoveSession() {
System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in "+ newDate());//
Session session = sessionMap.remove(Thread.currentThread());
if(session != null) {
session.close();
}
}
}

2 hibernate整合进spring后的事务处理

spring事物处理的方式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html

介绍常用的:

spring annotation声明式的事务管理

1) 事物处理层?

比如保存一个User,可以在Service层和DAOImpl层实现:

1
2
3
4
5
6
7
8
9
10
11
12
publicvoidsave(User u) {
userDAO.save(u);
}
publicvoidsave(User u) {
System.out.println("save user from:"+ this);
Session s = sessionFactory.openSession();
s.beginTransaction();
s.save(u);
s.getTransaction().commit();
s.close();
}

假如我们还有个日志记录,没保存一个User对象,要写入日志进入数据库。

而save(log) 和 save(user)必须处在同一事务中,所以不能放在DAOImpl层,事务处理在Service层。

2) 一般的事务处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();
throwe;
} finally{
sess.close();
}

并且要在实现层中的save()方法中也要加入事务处理,如果出出现异常要throws给上级处理!

并且实现层中的session必须使用openCurrentSession()得到。

1
2
Session s = sessionFactory.getCurrentSession();
s.save(u);

3) spring annotation事务处理

Beans.xml中引入相应的xml命名空间和相应配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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方法:
publicvoidsave(User u) {
Session s = sessionFactory.getCurrentSession();
s.save(u);
}
publicvoidsave(Log log) {
Session s = sessionFactory.getCurrentSession();
s.save(log);
}
Service层处理:
@Component("userService")
publicclassUserService {
UserDAO userDAO = null;
LogDAO logDAO = null;
publicLogDAO getLogDAO() {
returnlogDAO;
}
@Resource(name="logDAOMySQLImpl")
publicvoidsetLogDAO(LogDAO logDAO) {
this.logDAO = logDAO;
}
@Transactional
publicvoidsave(User u) {
userDAO.save(u);
Log log = newLog();
log.setMsg(u.getName() + " saved in "+ newDate());
logDAO.save(log);
}
publicUserDAO getUserDAO() {
returnuserDAO;
}
@Resource(name="userDAOMySQLImpl")
publicvoidsetUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
}

4) @Transactional详解

什么时候rollback

运行期异常,非运行期异常不会触发rollback

必须uncheck (没有catch)

不管什么异常,只要你catch了,spring就会放弃管理

事务传播特性:propagation_required

image

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();
	}

实际上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之类的操作了。

作者:syxChina
出处:http://syxchina.cnblogs.comhttp://hi.baidu.com/syxcs123
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
如果您阅读了我的文章并觉得有价值请点击此处,谢谢您的肯定1。
分享到:
评论

相关推荐

    spring-hibernate3.jar.zip

    在实际使用"spring-hibernate3.jar"时,我们需要理解Spring和Hibernate的集成原理。首先,Spring通过其优秀的AOP支持,可以实现对Hibernate的事务管理,使得事务的处理更加透明。其次,Spring的ApplicationContext...

    spring-orm-4.3.2.RELEASE.jar

    HibernateTemplate所属的架包是spring-orm-4.3.2.RELEASE.jar

    spring源码spring-framework-4.3.2.RELEASE

    2. **ORM集成**:Spring支持与各种ORM框架的集成,如Hibernate、MyBatis等。在`org.springframework.orm`包下,可以看到针对不同ORM的适配器,如`HibernateTemplate`和`HibernateDaoSupport`。 三、Web应用支持 1....

    尚硅谷-佟刚-spring使用的spring-framework-4.0.0.RELEASE

    《尚硅谷-佟刚-spring使用的spring-framework-4.0.0.RELEASE》是一个关于Spring框架的教程资源,其中特别关注了Spring与Hibernate的整合。在这个版本中,Spring Framework 4.0.0.RELEASE提供了对Hibernate的支持,...

    hibernate-core-3.6.10.Final.jar.zip

    《深入理解Hibernate Core 3.6.10.Final及其在Spring环境中的应用》 Hibernate,作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作。Hibernate Core是其核心组件,提供了数据持久化的核心...

    spring3.0,ssh

    标题中的"spring3.0,ssh"表明我们将讨论Spring框架的第三个主要版本(Spring 3.0)以及SSH(Struts、Spring、Hibernate)这三种技术的集成。SSH是Java Web开发中常用的三大开源框架,它们协同工作以构建高效、模块化...

    spring-boot 集成hibernate

    在本文中,我们将深入探讨如何将Spring Boot与Hibernate集成,并使用Druid作为数据库连接池。首先,我们需要理解这三个核心组件: 1. **Spring Boot**: 是一个由Pivotal团队提供的开源框架,它简化了创建独立的、...

    hibernate-release-4.2.2.Final

    理解并掌握其核心概念、配置方法以及整合框架的使用,将有助于提升项目的开发效率和代码质量。同时,了解并运用JAR包中的各个组件,可以更好地发挥Hibernate的潜能,为项目带来更高的灵活性和可维护性。

    spring-orm.jar

    Spring通过HibernateTemplate或HibernateDaoSupport类,提供了对Hibernate操作的便捷封装,降低了对Hibernate API的直接依赖。此外,Spring的事务管理可以透明地应用于Hibernate操作,简化了事务的配置和管理。 四...

    spring-1.0-rc1.zip

    同时,它还支持多种ORM框架,如Hibernate,通过`HibernateTemplate`类简化了Hibernate的使用。在`org.springframework.jdbc`和`org.springframework.orm`包中可以找到这些实现。 4. **MVC框架雏形**:虽然Spring ...

    Spring-hibernate结合使用全xml配置方式

    通过以上步骤,你已经成功地将Spring和Hibernate整合在一起,使用全XML配置方式实现了数据访问层。这种方式虽然较为繁琐,但能清晰地分离各层职责,便于管理和维护。在实际项目中,还可以考虑使用注解配置或者Spring...

    spring-framework-2[1].0.6.rar_Framework_spring 1.0_spring api_sp

    了解Spring Framework 1.0的API有助于开发者理解Spring框架的基本原理和工作方式,尽管现代项目通常使用更高版本的Spring,但基础知识是相通的,掌握这些可以帮助开发者更好地应对各种版本的Spring框架。

    官方原版源码spring-framework-5.0.14.RELEASE.zip

    在源码中,`JdbcTemplate`和`SimpleJdbcInsert`是简化JDBC操作的工具类,而`HibernateTemplate`和`HibernateInterceptor`则提供了对Hibernate的支持。 除了以上核心模块,Spring Framework 5.0.14.RELEASE还包含了...

    hibernate-release-5.2.2.Final.zip

    Hibernate可以很好地与Spring框架集成,通过Spring的`HibernateTemplate`或`SessionFactoryBean`简化事务管理和资源管理。 9. 性能优化: - 缓存策略:Hibernate提供了第一级缓存(Session级别的缓存)和第二级...

    spring-framework-4.1.0.RELEASE

    - **安全性增强**:整合Spring Security,提供身份验证和授权功能。 - **消息队列集成**:与RabbitMQ或Kafka结合,实现异步消息处理。 通过深入学习Spring Framework 4.1.0.RELEASE,开发者不仅可以提升自己的...

    structs+spring+hibernate整合jar包

    4. 使用Spring的`HibernateDaoSupport`或`HibernateTemplate`进行数据访问,也可以通过JPA接口进行操作。 5. 在Struts2 Action中注入Spring管理的Service,通过Service调用DAO完成业务逻辑。 通过这样的整合,我们...

    spring、spring-mvc学习总结-.pdf

    Spring 是一个广泛使用的Java应用程序框架,它以控制反转(Inversion of Control, IoC)和面向切面编程(Aspect Oriented Programming, AOP)为核心,旨在简化企业级应用的开发。Spring 的轻量级特性使其在不增加...

    struts,spring,hibernate整合

    【Struts、Spring、Hibernate整合】是Java Web开发中常见的技术栈组合,这三者各自承担着不同的职责:Struts负责MVC模式中的控制层,Spring作为应用框架提供依赖注入和事务管理,Hibernate则作为ORM工具处理数据库...

    Mina-Spring-Hibernate.rar_mina_mina hibernate_spring mina

    Spring通过HibernateTemplate或JpaTemplate提供了一套便捷的数据库操作接口,封装了Hibernate的操作,使得在Spring应用中使用Hibernate变得简单。同时,Spring还支持基于注解的事务管理,可以无缝地与Hibernate配合...

    spring+hibernate整合jar包

    - 使用HibernateTemplate或SessionFactoryBean配置来实现Spring与Hibernate的整合,使得在Spring环境下可以直接使用Hibernate的API。 5. **Spring MVC与Hibernate的结合**: - 在Spring MVC的Controller中,可以...

Global site tag (gtag.js) - Google Analytics