Spring+Hibernate : 声明式事务
来源:互联网 发布:php 判断是否刷新页面 编辑:程序博客网 时间:2024/06/08 00:33
本博文是作为初学者来学习和总结SH的声明式事务,
- Spring 中配置数据源的4中方式,主要关注c3p0数据源;
- Spring 的PropertyPlaceholderConfigurer :将properties属性值读入到xml文件中;
- 事务的常见六种传播特性介绍;
- Spring 和 Hibernate 集成声明式事务的四大步骤;
- Spring 和 Hibernate 集成过程中版本冲突问题;
- 项目代码演示;
- 总结语;
- Spring中配置数据源
1.1 Spring 自带的数据源: DriverManagerDataSource;
spring自身提供了三个没有连接池功能的数据源类(均位于org.springframework.jdbc.datasource 包中)
- DriverManagerDatasource
- SimpleDriverDatasource
SingleConnectionDatasource
xml代码:
<bean id="dataSource" <class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" /> <property name="username" value="scott" /> <property name="password" value="****" /> </bean>
1.2 第三方数据源:dbcp 数据源和 c3p0数据源
Apache CommonsDBCP数据源地址
c3p0数据源地址
1.2.1 dbcp
dbcp的配置依赖于2个jar包commons-dbcp.jar,commons-pool.jar。
xml配置:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" /> <property name="username" value="scott" /> <property name="password" value="****" /> </bean>
1.2.2 c3p0数据源
xml配置:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value=" oracle.jdbc.driver.OracleDriver "/> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="user" value="scott"/> <property name="password" value="****"/> </bean>
c3p0参数配置:
官网上对各个参数及其意义及如何配置说的很清楚;
acquireIncrement:当连接池中的连接用完时,C3P0一次性创建新连接的数目;
acquireRetryAttempts:定义在从数据库获取新连接失败后重复尝试获取的次数,默认为30;
acquireRetryDelay:两次连接中间隔时间,单位毫秒,默认为1000;
autoCommitOnClose:连接关闭时默认将所有未提交的操作回滚。默认为false;
automaticTestTable:
C3P0将建一张名为Test的空表,并使用其自带的查询语句进行测试。breakAfterAcquireFailure:获取连接失败将会引起所有等待获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调
用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认为
false;checkoutTimeout:当连接池用完时客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒,默认为0;
connectionTesterClassName:
通过实现ConnectionTester或QueryConnectionTester的类来测试连接,类名需设置为全限定名。默认为
com.mchange.v2.C3P0.impl.DefaultConnectionTester;idleConnectionTestPeriod:隔多少秒检查所有连接池中的空闲连接,默认为0表示不检查;
initialPoolSize:初始化时创建的连接数,应在minPoolSize与maxPoolSize之间取值。默认为3;
maxIdleTime:最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0;
maxPoolSize:连接池中保留的最大连接数。默认为15;
maxStatements:JDBC的标准参数,用以控制数据源内加载的PreparedStatement数量。但由于预缓存的Statement属
于单个Connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素,如果maxStatements与
maxStatementsPerConnection均为0,则缓存被关闭。默认为0;maxStatementsPerConnection:连接池内单个连接所拥有的最大缓存Statement数。默认为0;
numHelperThreads:C3P0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能,通过多线程实现多个操作同时被执行。默认为3;
preferredTestQuery:定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个参数能显著提高测试速度。测试的表必须在初始数据源的时候就存在。默认为null;
propertyCycle: 用户修改系统配置参数执行前最多等待的秒数。默认为300;
testConnectionOnCheckout:因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都
将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。默认为false;testConnectionOnCheckin:如果设为true那么在取得连接的同时将校验连接的有效性。默认为false。
1.4 JNDI数据源
Spring应用程序通常部署在Java EE应用服务器中,如JBoss,Tomcat这样的Web容器。这些服务器允许配置通过jndi获取数据源。
在spring配置文件中如下设置:
<beans> <jee:jndi-lookup id="datasource" jndi-name="java:comp/env/jdbc/myDataSource"/></beans>
在服务器中的配置以tomcat为例:
<Resource name="jdbc/myDataSource" type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@193.23.42.6:1521:myDataSource" username="scott" password="****" maxActive="80" />
- Spring 的PropertyPlaceholderConfigurer :将properties属性值读入到xml文件中;
2.1 在这之前我们先看看Hibernate的文件 hibernate.cfg.xml 是怎么配置,
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:ORCL</property> <property name="connection.username">scott</property> <property name="connection.password">qian</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.OracleDialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property <property name="hbm2ddl.auto">update</property> <mapping resource="com/qian/domain/User.hbm.xml"/> </session-factory></hibernate-configuration>
2.2 接下来,我们以读取配置文件的方式配置数据源,那么hibernate.cfg.xml如下:
hibernate.cfg.xml
<hibernate-configuration> <session-factory> <!-- 配置hibernate基本信息 --> <!-- 1.数据源配置在IOC容器中,此处不需要额外配置 --> <!-- 2.关联的.hbm.xml文件也可以在IOC容器配置SessionFactory时配置 --> <!-- 3.此处配置hibernate的基本信息:数据库方言、SQL显示及格式化,及生成数据表的策略,二级缓存等 --> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.OracleDialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <property name="hibernate.format_sql">true</property <property name="hibernate.hbm2ddl.auto">update</property> <mapping resource="com/spring/trans/domain/User.hbm.xml"/> </session-factory></hibernate-configuration>
2.3 使用c3p0在 spring IOC容器中显示配置
applicationContext.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="user" value="scott"/> <property name="password" value="qian"/> <property name="initialPoolSize" value="3"/></bean>
2.4 将数据源的配置信息放入到 jdbc.properties中如下:
jdbc.properties
jdbc.driver=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc:oracle:thin:@localhost:1521:ORCLjdbc.userName=scottjdbc.password=qianjdbc.initialPoolSize=3
2.5 应用spring的PropertyPlaceholderConfigurer将上下文(配置文件) 中的属性值在 xml 文件中以 ${key} 形式读入,
第一种方式:
<bean id="" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:jdbc.properties</value> </property></bean>
如要读取读个配置文件 使用方法setLocations:
<bean id="" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:infors.properties</value> </list> </property></bean>
第二种方式:为了简化上述这样的配置,Spring 给出了<context: property-placeholder/>
元素,因此上式可以简化为:
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:property-placeholder location="classpath:jdbc.properties,classpath:infors.properties"/>
此时,数据源配置如下:
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.userName}"/> <property name="password" value="${jdbc.password}"/> <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/></bean>
如要改动相关信息,我们只需要去改properties文件即可;
- 事务传播特性介绍
事务:是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,(要么成功,要么失败)。
事务特性分为四个:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持续性(Durability)简称ACID。
Spring事务对数据库事务操作的一次封装,相当于把使用JDBC代码开启、提交、回滚事务进行了封装。
事务的传播特性: 是保证事务是否开启,业务逻辑是否使用同一个事务的保证。
- PROPAGATION_REQUIRED:
- 如果存在一个事务,则支持当前事务。如果没有事务则开启
- PROPAGATION_REQUIRES_NEW:
- 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
- PROPAGATION_SUPPORTS:
- 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
- PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
- PROPAGATION_MANDATORY:
- 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
- PROPAGATION_NEVER:
- 总是非事务地执行,如果存在一个活动事务,则抛出异常
- Spring 和 Hibernate 集成声明式事务的四大步骤;
4.1 配置SessionFactory, 将hibernate.cfg.xml 文件交给Spring,通过Spring提供的 LocalSessionFactoryBean配置Hibernate的SessionFactory
<!-- Step 0 配置自己的dataSource, 早期我们在hibernate.cfg.xml中配置的直接 --><!-- 把hibernate.cfg.xml给了spring就好,现在我们在spring applicationContext.xml配置数据源 --><!-- ** myDataSource ** --><bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.userName}"/> <property name="password" value="${jdbc.password}"/> <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/></bean>
<!--Step 1: 配置Hibernate的SessionFactory,通过spring提供的 LocalSessionFactoryBean配置--><!-- ** mySessionFactory** --><bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource"> <!-- step 0中的数据源名称 --> <ref bean="myDataSource"/> </property> <property name="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> <!-- 如果我们不在hibernate.cfg.xml中配置User.hbm.xml和Log.hbm。xml我们也可以在这配置 --> <!-- <property name="mappingLocations"> <value>classpath:com/spring/trans/domain/*.hbm.xml</value> </property> --></bean>
4.2 配置事务管理器,将spring生产的sessionFactory注入到事务管理器上,
<!--Step 2: 配置 Spring 的声明式事物 --> <!-- ** myTransactionManager --><bean id="myTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory"> <!-- step 1中的SessionFactory名称 --> <ref bean="mySessionFactory"/> </property></bean>
4.3 配置事务的转播特性
<!--Step 3: 配置事物属性 ,需要事物管理器--> <!-- **myTxAdvice** --><!-- step 2 中的myTransactionManager名称 --><tx:advice id="myTxAdvice" transaction-manager="myTransactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="find*" propagation="REQUIRED" read-only="true"/> </tx:attributes></tx:advice>
4.4 配置事务的切点,并将事务属性和切点管理起来
<!--Step 4: 配置事物切点,并把事物属性和切点关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.spring.trans.manager.*.*(..))" id="myPointcut"/> <!-- step 3: myTxAdvice --> <aop:advisor advice-ref="myTxAdvice" pointcut-ref="myPointcut"/></aop:config>
注意:
最后将将spring生成的SessionFactory注入给IOC容器中的实体bean,要不它找不到SessionFactory。
<bean id="userManagerImpl" class="com.spring.trans.manager.UserManagerImpl"> <!-- ** 将spring生成的sessionFactory注入到Ioc需要使用的类中; --> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> <property name="logManager"> <ref bean="logManagerImpl"/> </property> </bean>
Spring 和 Hibernate 集成过程中版本冲突问题;
5.1 在继承 Spring 和Hibernate即使都配置对了,还是会报各种异常,大致为,类找不到,这个好解决,加入相应的架包就可以解决; BeanCreateException等异常,我原来用的Spring 4.3 和Hibernate 5.1.10 一直出现异常,后将Hibernate 换成最新的Hibernate5.2.11就好了;所以很多时候,我们要关注是不是版本冲突导致的;
- 项目代码示例:
这里就展示下项目结构和用到的架包,如果有需要源码的朋友,可以留邮箱或者在这里下载;
项目结构:
Spring4.3.0架包:
Hibernate5.2.11架包:
applicationContext-commons.xml文件内容
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="user" value="scott"/> <property name="password" value="qian"/> <property name="initialPoolSize" value="2"/> </bean> --> <!-- Step 1 --> <!-- <bean id="" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:jdbc.properties</value> </property> </bean> --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- Step 2 --> <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.userName}"/> <property name="password" value="${jdbc.password}"/> <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/> </bean> <!-- ========================================================================================================= --> <!--Step 1: 配置Hibernate的SessionFactory,通过spring提供的 LocalSessionFactoryBean配置--> <bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="myDataSource"/> </property> <property name="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> <!-- 如果我们不在hibernate.cfg.xml中配置User.hbm.xml和Log.hbm。xml我们也可以在这配置 --> <!-- <property name="mappingLocations"> <value>classpath:com/spring/trans/domain/*.hbm.xml</value> </property> --> </bean> <!--Step 2: 配置 Spring 的声明式事物 --> <bean id="myTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> </bean> <!--Step 3: 配置事物属性 ,需要事物管理器--> <tx:advice id="myTxAdvice" transaction-manager="myTransactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="find*" propagation="REQUIRED" read-only="true"/> </tx:attributes> </tx:advice> <!--Step 4: 配置事物切点,并把事物属性和切点关联起来 --> <aop:config> <aop:pointcut expression="execution(* com.spring.trans.manager.*.*(..))" id="myPointcut"/> <aop:advisor advice-ref="myTxAdvice" pointcut-ref="myPointcut"/> </aop:config><!-- <bean id="userManagerImpl" class="com.spring.trans.manager.UserManagerImpl"> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> <property name="logManager"> <ref bean="logManagerImpl"/> </property> </bean> <bean id="logManagerImpl" class="com.spring.trans.manager.LogManagerImpl"> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> </bean>--></beans>
补充一点:怎么在Eclipse下配置 Hibernate 和 Spring相应标签的快捷键;
- hibernate.cfg.xml 和 *.hbm.xml 快捷键
在下载的hibernate的文件中,找打这两个文件,
在Eclipse–》Preference–》XML–>xml catalog下如下添加:
- spring的 applicationContext.xml文件快捷键配置类似;
Okay, okay. That is all, maybe too long. If you want to get the source code of this program in the blog, you can download here , or leave your email in the comments for free.
- Spring+Hibernate声明式事务
- Spring+Hibernate 声明式事务
- Spring+Hibernate : 声明式事务
- Spring+Hibernate声明事务
- Spring结合Hibernate声明式事务配置
- Spring和Hibernate集成--声明式事务
- Spring Hibernate 配置声明式事务无效
- spring+hibernate,采用声明式事务
- Hibernate+Spring中的声明式事务
- spring hibernate 声明式事务配置笔记
- Spring hibernate 声明式事务配置
- Spring与Hibernate集成声明式事务
- 【spring 7】spring和Hibernate的整合:声明式事务
- spring声明式事务
- Spring---声明式事务
- Spring声明式事务
- Spring声明式事务
- spring 声明式事务
- Vivify动画库
- JS 去重与去空值
- 在windows下静默安装JDKJRE并指定安装目录
- 工作日常记录 2017-09-21
- Fiddler
- Spring+Hibernate : 声明式事务
- tpshop 阿里云短信sdk使用和带链接短信实现
- Spring之Bean总结(二)
- Linux 系统下 MPI环境的安装与配置
- 使用Springcloud及Docker实现微服务架构
- iPhone/iPad/Android UI尺寸规范
- 重启服务器后,rabbit用户丢失问题
- 清除浮动的几种方式?
- App安装失败的几种情况