spring怎么自动创建spring4 hibernate5 seeion并开启事物

Spring+Hibernate集成后事务与Session的一些理解_博客园
当前位置: >
>Spring+Hibernate集成后事务与Session的一些理解
Spring+Hibernate集成后事务与Session的一些理解
& 作者:快鸟 & 来源: 博客园-kevin-yuan &
Spring的配置文件,在web.xml加载时,就按照类得映射给动态注入了,而且对于其中需要加载的hibernate配置文件,也只加载一次,就把sessionFactory注入给对象中。然后在类中如果需要取得sessionFactory,只需继承HibernateDaoSupport来取得session.不需要在类中写set方法,因为由HibernateDaoSupport中提供。
以往我们单独使用Hibernate编程式事务,我们都是这样的步骤:
Session&session=HibernateUtils.getSessionFactory().getCurrentSession();
session.beginTranstraction();//开启事务
session.save(…..);
log.add(log);//假设log.add是在另一个类中的操作数据库的方法。其中也要用session来操作。HibernateUtils.getSessionFactory().getCurrentSession().save(…..);
session.getTranstraction().commit();
有异常则session.getTranstraction().rollback();
* 采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()
创建的session则不会.所以以上的session是一直都是一个session.
个人认为:(不管你要执行多少条语句,最后一起commit,就是一个事,也就是一个事务。一个线程只存在一个session)
* 采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭
使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:
*如果使用的是本地事务(jdbc事务)
&propertyname=&hibernate.current_session_context_class&&thread&/property&
* 如果使用的是全局事务(jta事务)
&propertyname=&hibernate.current_session_context_class&&jta&/property&&&& &
采用Spring之后我们采用采用声明式事务
1、声明式事务配置
&&&&&&&& *配置SessionFactory
&&&&&&&& *配置事务管理器
&&&&&&&& *事务的传播特性
&&&&&&&& *那些类那些方法使用事务
2、了解事务的几种传播特性
&&&&&&&& 1.&&&&& PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
&&&&&&&& 2.&&&&& PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
&&&&&&&& 3.&&&&& PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
&&&&&&&& 4.&&&&& PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
&&&&&&&& 5.&&&&& PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
&&&&&&&& 6.&&&&& PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
&&&&&&&& 7.&&&&& PROPAGATION_NESTED:如果一个活动的事务存在,则运行此文来自: 马开东博客
转载请注明出处 网址:
在一个嵌套的事务中. 如果没有活动事务,
&&&&&&&& &&&& 则按TransactionDefinition.PROPAGATION_REQUIRED属性执行
&&&&&&& 举一个例子:required
public class UserManagerImpl extends HibernateDaoSupport implements UserManager {&& && & && private LogManager logM&&&&
&&&&&& public void addUser(User user) {& &&&&&&&&& this.getHibernateTemplate().save(user);&&&& & & && Log log = new Log();&&&&&&&&&&& log.setType(&安全日志&);&&&&&&&&&&& log.setDetail(&xxx进入系统&);&&& & & & & log.setTime(new Date());&&&&&&&&&&& logManager.addLog(log);& & & }
public class LogManagerImpl extends HibernateDaoSupport implements LogManager {&& &public void addLog(Log log) {&& &&& &this.getHibernateTemplate().save(log);&& &}}
在add方法上都配置Required属性,这样在执行addUser时,会开启新事务,然后在方法执行后,再进行事务提交。其中遇到了addlog方法,它发现当前有事务然后就用当前事务,然后当当前事务提交后,他也跟着提交。
3、Spring事务的隔离级别
&&&&&&&& 1.&&&&& ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
&&&&&&&& &&&& 另外四个与JDBC的隔离级别相对应
&&&&&&&& 2.&&&&& ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
&&&&&&&& &&&& 这种隔离级别会产生脏读,不可重复读和幻像读。
&&&&&&&& 3.&&&&& ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
&&&&&&&& 4.&&&&& ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
&&&&&&&& &&&& 它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
&&&&&&&& 5.&&&&& ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
&&&&&&&& &&&& 除了防止脏读,不可重复读外,还避免了幻像读。
4、编写业务逻辑方法
&&&&&&&& *继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是
&&&&&&&& &Hibernate Session的轻量级封装
&&&&&&&& *默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的
&&&&&&&& *编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
&&&&&&&& *关于事务边界的设置,通常设置到业务层,不要添加到Dao上&
相关阅读:
来源:(微信/QQ:,微信公众号:makaidong-com) &&&&&& 欢迎分享本文,转载请保留出处!
&&&&&& 【原文阅读】:
上一篇:没有了
【相关文章】
每日最新文章
每日最热文章
spring组件扫描
本周最热文章
本月最热文章
本年最热文章
Powered by
Copyright &
www.makaidong.com, All Rights ReservedSpring+Hibernate4 Junit 报错No Session found for current thread
论坛上有另外一篇更全面的帖子,jinnianshilongnian写的:http://www.iteye.com/topic/1120924&
本文的环境是:&
spring-framework-3.1.0&
hibernate-4.1.6&
junit-4.10&
这里大部分是参考我以前熟悉的配置方法,只是把hibernate3升级到hibernate4,其实差不了很多,只要注意几个要点:&
1、以前集成hibernate3和spring的时候,spring的ORM包里提供了HibernateSupport和HibernateTemplate这两个辅助类,我用的是HibernateTemplate。不过在Hibernate4里,spring不再提供这种辅助类,用的是hibernate4的原生API&
2、集成hibernate4之后,最小事务级别必须是Required,如果是以下的级别,或者没有开启事务的话,无法得到当前的Session&
Java代码&&
执行这行代码,会抛出No Session found for current thread&
对于运行时,这个可能不是很大的问题,因为在Service层一般都会开启事务,只要保证级别高于Required就可以了。可是由于在Dao层是不会开启事务的,所以针对Dao层进行单元测试就有困难了。&
解决的办法是,或者在Dao层的单元测试类上,开启事务。或者专门准备一个for unit test的配置文件,在Dao层就开启事务。我采用的是前者&
首先是目录结构,这里暂时还没有集成struts2、spring-mvc等web框架,也尚未包含js、css、jsp等目录&
这里除了servlet规范规定的web.xml必须放在WEB-INF下之外,其他的所有配置文件,都放在src根目录下。这样做的好处是,后续所有需要引用配置文件的地方,都可以统一用classpath:前缀找到配置文件。之前试过有的文件放在WEB-INF下,有的放在src根目录下,所以在引用的地方会不太统一,比较麻烦。&
当然无论配置文件怎么放,只要恰当使用classpath:和file:前缀,都是能找到的,只是个人选择的问题。另外,由于现在配置文件还比较少,所以直接扔到src根目录下没什么问题,如果配置文件增多了,可以再进行划分&
接下来是web.xml&
这里没有什么要特别注意的,只是声明了beans.xml的路径。这里的servlet是配置cxf的,与hibernate没有关系。因为目标是要搭一个完整的开发框架,所以把cxf也事先放上了&
接下来是spring的配置文件beans.xml&
这里有几点要注意的:&
这里把jdbc驱动的参数,放到了专门的配置文件里,改动起来会比较方便。另外数据库连接池在实际生产环境可以考虑切换一下,比如听说阿里巴巴出的druid就挺不错,jboss和WAS自带的连接池也是不错的&
这里的sessionFactory改成org.springframework.orm.hibernate4.LocalSessionFactoryBean,如果ORM映射采用的不是配置文件,是用注解的话,以前hibernate3有一个AnnotationSessionFactoryBean,在hibernate4里没看到&
这里ORM映射用的是配置文件,其实用注解也差不多&
可以避免启动容器时报的一个错误:&
Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException&
这个错误其实是无所谓的,不过还是不要报错好看一点&
这里是开启事务,用的是注解,比用配置文件简单一点。&
用配置文件的好处,是事务声明比较集中,不需要在每个Service层接口上单独声明。缺点是Service中的方法,命名规范需要事先约定好,否则事务就不能生效&
用注解的好处,是Service中的方法命名不需要特别规定,缺点是没有做到集中声明,如果在某个Service层的接口忘记声明事务,那么事务就无法生效&
两种方法各有好处,我个人更喜欢用注解&
然后是DAO层的结构&
首先有一个通用的DAO接口,然后有一个通用的DAO抽象实现类。每个具体业务DAO接口,继承通用DAO接口,具体业务DAO实现,继承通用DAO抽象实现类&
Java代码&&
因为只是示例,这里的方法不是很多,只包含了基本的增删改查方法&
Java代码&&
这个抽象类实现了IGenericDAO的所有方法,具体业务DAO的实现类,就不需要重复实现这些方法了。&
这里因为session.get()和session.load()方法,都需要传入一个Class类型的参数,所以定义了entityClass字段,在具体业务类的构造方法中传入,下面会看到。另外有一个办法是用反射的方法,来获取entityClass字段,就不需要在具体子类的构造方法中再传入了。不过我个人觉得传入也不是很麻烦,就没有这么做&
这个类除了实现了IGenericDAO里定义的public方法之外,还提供了protected的queryForObject()和queryForList()方法,可以为具体子类提供一些便利&
这个通用DAO还不是很完善,主要是还可以补充更多的方法,以及考虑分页。为了简化的需要,这里省略了&
Java代码&&
这是具体业务DAO的接口,除了通用的方法之外,增加了一个按照name查询的方法,所以就要单独定义此方法&
Java代码&&
这是具体业务DAO的实现类,实现了接口里的queryByName()方法,并且在构造参数中传入了User.class,用于初始化GenericDAO里的entityClass字段&
此外,这个类需要用@Repository注解,声明为spring bean&
DAO层里是不能声明事务的,也不能自行捕获异常,如果有特殊需求必须捕获的话,也要在处理之后,重新抛出来。否则Service层的事务就失效了&
接下来是Service层&
Java代码&&
只要在接口上用@Transactional注解,此接口内的所有方法就自动声明为事务了,方法即是事务的边界。&
注意事务是在接口上声明的,一般不在实现类上声明&
后面的propagation参数,至少要到REQUIRED,否则No Session found for current thread,我也不知道这算不算一个BUG,还是spring认为是一个强制要求&
Java代码&&
这个Service的实现类就很简单了,不需要重复声明事务,但是需要用@Service注解将自身声明为一个spring bean(因为可能还会注入上层),另外用@Autowired注解,将之前声明的DAO注入&
接下来说明一下单元测试的方法,在想做单元测试的类上,用右键菜单New--&JUnit Test Case&
这里要注意Source folder选到test,不然就会生成到src目录下了,然后可以视情况勾选setUp()&
生成的单元测试类&
Java代码&&
注解为@Test的方法,会被认为是单元测试方法被执行,注解为@Before的方法,会在每个单元测试方法执行之前被执行&
Java代码&&
这里是把要单元测试的目标类注入进来&
下面重点介绍一下类上面的几个注解:&
Java代码&&
加上@RunWith注解之后,单元测试类会在spring容器里执行,这会带来很多便利。&
@ContextConfiguration注解,可以指定要加载的spring配置文件路径。如果对spring配置文件进行了恰当的拆分,就可以在不同的单元测试类里,仅加载必要的配置文件&
Java代码&&
这行注解是最关键的,前面已经提到,因为在DAO层是没有声明事务的,所以如果直接执行的话,就会抛出No Session found for current thread&
所以需要加上这句注解,在执行单元测试时,开启事务,就可以规避这个问题。同时也不会影响到实际的事务&
此外还引入了一个额外的好处,就是加上了这个注解之后,单元测试对数据库的改动会被自动回滚,避免不同单元测试方法之间的耦合。这个特性在实际跑单元测试里是很方便的&
实际运行一下这个单元测试类,可以在控制台看到以下输出:&
19:37:42 org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction&
信息: Began transaction (1): transaction manager [org.springframework.orm.hibernate4.HibernateTransactionManager@183d59c];
rollback [true]&
1903 [main] WARN& o.h.hql.internal.ast.HqlSqlWalker - [DEPRECATION] Encountered positional parameter near line 1,
column 60.& Positional parameter are c use named parameters or JPA-style positional parameters instead.&
Hibernate:&
&&& select&
&&&&&&& book0_.ID as ID0_,&
&&&&&&& book0_.NAME as NAME0_,&
&&&&&&& book0_.ISBN as ISBN0_&
&&&&&&& developframeworkschema.book book0_&
&&& where&
&&&&&&& book0_.ISBN=?&
19:37:42 org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction&
信息: Rolled back transaction after test execution for test context&
每个方法开始之前,都会开启一个新事务,在执行完毕之后,该事务都会被回滚&
其中还有一行警告信息:[DEPRECATION] Encountered positional parameter near line 1, column 60.& Positional parameter are considered
use named parameters or JPA-style positional parameters instead.&
这是因为在GenericDAO中采用了hibernate4不推荐的写法:&
Java代码&&
hibernate4的建议,是把&
Java代码&&
Java代码&&
鉴于自动回滚这个特性很方便,对Service层组件进行单元测试的时候,也推荐加上@Transactional注解&
对于spring3和hibernate4的集成,本文就简单介绍到这里,欢迎补充
转自:http://www.iteye.com/topic/1126047
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?spring hibernate怎么开启事务_百度知道
spring hibernate怎么开启事务
我有更好的答案
声明式事务,自动开启,在spring的配置文件里配置,你加到service层,自动在service层开启
采纳率:45%
为您推荐:
其他类似问题
hibernate的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。博客分类:
1、在单独的使用Hibernate时,在Hibernate映射文件(*.hbm.xml)中配置好各个类的关系,然后再Hibernate配置文件(hibernate.cfg.xml)中添加属性可以自动在数据库中创建表结构(注:只能创建表,而非创建库)。
主要代码如下:
&!--自动在数据库中建立表 --&
&&&&&& &property name="hbm2ddl.auto"&create&/property&
2、在我使用spring mvc 整合hibernate时,代码如下:
&property name="hibernateProperties"&
&prop key="hibernate.dialect"&org.hibernate.dialect.SQLServerDialect&/prop&
&prop key="hibernate.show_sql"&true&/prop&
&prop key="hibernate.hbm2ddl.auto"&create&/prop&
&/property&
JPA方法:
META-INF/persistence.xml
&?xml version="1.0" encoding="UTF-8" standalone="yes"?&
&persistence version="1.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/persistence"&
&persistence-unit name="org.jbpm.persistence.jpa"
transaction-type="RESOURCE_LOCAL"&
&provider&org.hibernate.ejb.HibernatePersistence&/provider&
&properties&
&property name="hibernate.max_fetch_depth" value="3" /&
&property name="hibernate.hbm2ddl.auto" value="update" /&
&property name="hibernate.show_sql" value="false" /&
&property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /&
&property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/&
&property name="hibernate.cache.use_query_cache" value="true"/&
&property name="hibernate.cache.use_second_level_cache" value="true"/&
&property name="hibernate.generate_statistics" value="true"/&
&property name="hibernate.use_sql_comments" value="true"/&
&property name="hibernate.generate_statistics" value="true"/&
&/properties&
&/persistence-unit&
&/persistence&
applicationContext.xml
&bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&
&property name="dataSource" ref="xDataSource" /&
&property name="persistenceUnitName" value="org.jbpm.persistence.jpa" /&
值说明:
validate&&&&&&&&&&&&&& 加载hibernate时,验证创建数据库表结构
create&&&&&&&&&&&&&&&&& 每次加载hibernate,重新创建数据库表结构。
create-drop&&&&&&& 加载hibernate时创建,退出是删除表结构
update&&&&&&&&&&&&&&&& 加载hibernate自动更新数据库结构
浏览: 1594020 次
来自: 珠海
很有用,谢谢
厉害,困扰了我很久
非常好,很实用啊。。
你好,你能把能讓這個程序的運行起來的代碼發我一下嗎?非常著急需 ...
可能配置有问题.
这文章我只是收藏转发而已, 并没有实 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'【图片】&&[新人求助] hibernate4+spring3.2的一个问题,大神进来救救吧&&【java吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:707,557贴子:
&&[新人求助] hibernate4+spring3.2的一个问题,大神进来救救吧&&收藏
新手刚接触hibernate4+spring3.2不久,搭了一个项目,有个问题解决不了,受不了前来大java吧求解,废话少说上代码.工程目录在执行save的方法时抛异常hib-config-baen.xml想知道什么的,随便可以
看看hibernate 的配置文件
no seeion是hibernate的常见问题了,把session放到view层开启和关闭就解决了
楼上是hibernate 的配置文件
这个是你获取session有问题,不知道楼主是怎么获取session的
1、web.xml配置&!-- 配置session --&&filter&&filter-name&openSession&/filter-name&&filter-class&org.springframework.orm.hibernate4.support.OpenSessionInViewFilter&/filter-class&&/filter&&filter-mapping&&filter-name&openSession&/filter-name&&url-pattern&/*&/url-pattern&&/filter-mapping&2、在持久化层中,session的获取方法用getcurrentSession,这个是线程安全的,最好不要用openSession方法3、还没解决的话-------
感谢大java吧,问题已经解决
那你肯定能学好java。。。
最后怎么解决的?求详细说下,谢谢楼主,楼主是好人
菜鸟路过        ---自己的心如围城冰封,必然孤独一生
这个拿session.之前报错是因为没配web.xml 根据8楼添加语句就没事了
登录百度帐号}

我要回帖

更多关于 spring hibernate整合 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信