Hibernate4+Spring3实现声明式事务管理

概述:

还像往常一样先了解下基础知识:
Hibernate是一个开源的ORM框架,能自动为对象生成相应SQL并透明的持久化对象到数据库,我们首先来了解一下什么是“ORM”。
ORM全称对象关系映射(Object/Relation Mapping),指将Java对象状态自动映射到关系数据库中的数据上,从而提供透明化的持久化支持,即把一种形式转化为另一种形式。
对象与关系数据库之间是不匹配,我们把这种不匹配称为阻抗失配,主要表现在: 
  • 关系数据库首先不支持面向对象技术,如继承、多态;
  • 关系数据库是由表来存放数据,而面向对象使用对象来存放状态;
  • 如何将对象透明的持久化到关系数据库表中;
如果一个对象存在横跨多个表的数据,应该有一种策略来对象建模和映射。
其中这些阻抗失配只是其中的一小部分,比如还有如何将SQL集合函数结果集映射到对象,如何在对象中处理主键等。ORM框架就是用来解决这种阻抗失配,提供关系数据库的对象化支持。
目前已经有许多ORM框架产生,如Hibernate、JDO、JPA、iBATIS等等,这些ORM框架各有特色,Spring对这些ORM框架提供了很好的支持。

集中式声明事务管理源码下载 注解式事务管理源码下载 结合原文更容易理解

下面来看具体配置:


集中式声明事务管理:    


pom.xml


1)先来看jar含义
虽然只加了这么几个包,但是来看看maven帮我们添加的最终依赖包,从这就可以看出maven管理项目的好处:
虽然不是每个包都被用到但是这样就会减少管理jar的繁琐,况且也可以手动的删除这些jar,maven还是很不错吧!
[INFO]    antlr:antlr:jar:2.7.7:compile
               一个语言转换工具,Hibernate利用它实现 HQL 到 SQL 的转换    
[INFO]    aopalliance:aopalliance:jar:1.0:compile
              包含了针对面向切面的接口。
[INFO]    com.alibaba:druid:jar:0.2.25:compile
               阿里巴巴开发的一个高效的数据库连接池:druid。
[INFO]    commons-logging:commons-logging:jar:1.1.1:compile
              是使用Spring-core.jar的必备包
[INFO]    dom4j:dom4j:jar:1.6.1:compile
               dom4j XML 解析器
[INFO]    junit:junit:jar:4.11:compile
               测试工具
[INFO]    mysql:mysql-connector-java:jar:5.1.26:compile
               连接mysql插件
[INFO]    org.aspectj:aspectjweaver:jar:1.7.3:compile
                切面用到的包,也就是AOP
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:compile
               是junit的依赖包,在4.11这个版本里,不包含这个包,4.8版本就不需要这个包
[INFO]    org.hibernate:hibernate-core:jar:4.2.5.Final:compile
                 hibernate核心包
[INFO]    org.hibernate.common:hibernate-commons-annotations:jar:4.0.2.Final:compile
                hibernate的annotation必备包
[INFO]    org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile
                实体类中使用的注解都是在这个JAR包中定义的
[INFO]    org.javassist:javassist:jar:3.15.0-GA:compile
               代码生成工具, Hibernate用它在运行时扩展 Java类和实现,同cglib
[INFO]    org.jboss.logging:jboss-logging:jar:3.1.0.GA:compile
               Hibernate的默认包
[INFO]    org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:jar:1.0.1.Final:compile
               Hibernate的默认包
[INFO]    org.springframework:spring-aop:jar:3.2.4.RELEASE:compile
              这个jar文件包含在应用中使用Spring的AOP特性时所需的类。使用基于AOP的Spring特性,如声明型事务管理(Declarative Transaction Management  ),也要在应用里包含这  个jar包。 
[INFO]    org.springframework:spring-beans:jar:3.2.4.RELEASE:compile
               这个jar文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。
              springIoC(依赖注入)的基础实现
              如果应用只需基本的IoC/DI支持,引入spring-core.jar及spring-beans.jar文件就可以了。

[INFO]    org.springframework:spring-context:jar:3.2.4.RELEASE:compile
                spring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,如 邮件 
             服务、任务调度、JNDI定位、EJB 集成、远程访问、 缓存以及各种视图层框架的封装等。

[INFO]    org.springframework:spring-core:jar:3.2.4.RELEASE:compile
               这个jar文件包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。
[INFO]    org.springframework:spring-expression:jar:3.2.4.RELEASE:compile
              spring 表达式语言也就是 spel表达式
[INFO]    org.springframework:spring-jdbc:jar:3.2.4.RELEASE:compile
              这个jar文件包含对Spring对JDBC数据访问进行封装的所有类。
[INFO]    org.springframework:spring-orm:jar:3.2.4.RELEASE:compile
              这个jar文件包含Spring对DAO特性集进行了扩展,使其支持 iBATIS、JDO、OJB、TopLink,因为Hibernate已经独立成包了,现在不包含在这个包里了。这个jar文件里大部分的类都        要依赖 spring-dao.jar里的类,用这个包时你需要同时包含spring-dao.jar包。 
[INFO]    org.springframework:spring-tx:jar:3.2.4.RELEASE:compile
             也就是spring对于事务的一些管理


  虽然我们这个案例有很多没有用到的jar,但是不管怎么样至少我们不用对用哪个jar而烦心了,但是maven的添加也是由于根据包里所必须的类或方法而添加的虽然我们不用。



再来看一看包之间的依赖关系:
[INFO] +- junit:junit:jar:4.11:compile
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:compile
[INFO] +- mysql:mysql-connector-java:jar:5.1.26:compile
[INFO] +- com.alibaba:druid:jar:0.2.25:compile
[INFO] +- org.springframework:spring-context:jar:3.2.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-aop:jar:3.2.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:3.2.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-core:jar:3.2.4.RELEASE:compile
[INFO] |  |  \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  \- org.springframework:spring-expression:jar:3.2.4.RELEASE:compile
[INFO] +- org.springframework:spring-orm:jar:3.2.4.RELEASE:compile
[INFO] |  +- aopalliance:aopalliance:jar:1.0:compile
[INFO] |  +- org.springframework:spring-jdbc:jar:3.2.4.RELEASE:compile
[INFO] |  \- org.springframework:spring-tx:jar:3.2.4.RELEASE:compile
[INFO] +- org.hibernate:hibernate-core:jar:4.2.5.Final:compile
[INFO] |  +- antlr:antlr:jar:2.7.7:compile
[INFO] |  +- org.jboss.logging:jboss-logging:jar:3.1.0.GA:compile
[INFO] |  +- dom4j:dom4j:jar:1.6.1:compile
[INFO] |  +- org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:jar:1.0.1.Final:compile
[INFO] |  +- org.hibernate.common:hibernate-commons-annotations:jar:4.0.2.Final:compile
[INFO] |  \- org.javassist:javassist:jar:3.15.0-GA:compile
[INFO] +- org.aspectj:aspectjweaver:jar:1.7.3:compile
[INFO] \- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile
 
明白了吧!!是不是对jar不是那么畏惧啦!!

2)再来看看maven插件包的含义:
 (1).maven-compiler-plugin:
    <!-- compiler插件, 设定JDK版本 -->
  maven-compiler-plugin用来编译Java代码

 (2).maven-war-plugin:
<!-- war插件用于打包成war项目 -->
使用maven-war-plugin这个插件可以在执行打包命令的时候指定我要打哪个环境的包, 而不需要去关注我现在要用什么配置文件了.当然只适用于Maven项目.
虽然不是web项目但是可以把这个项目当脚手架啊!还会扩展成web项目的所以先加上吧!

 (3).maven-resources-plugin:
<!-- resource插件, 设定编码 -->
maven-compiler-plugin用来编译Java代码,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources,很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。
此外,资源文件过滤也是Maven的一大特性,你可以在资源文件中使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就可以针对不同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。
xml、properties文件都是资源文件,编码的时候遇到中文总要进行转码!用什么编码?UTF-8,那就记得强制

(4).maven-jar-plugin
用于打成jar包
(5). maven-source-plugin:
<!-- 源码插件 -->
maven-source-plugin提供项目自动将源码打包并发布的功能

(6). maven-clean-plugin:
清除target 文件夹下由install产生的一些东西例如 war
(7). maven-install-plugin:
用于自动安装项目的主要工件(JAR、WAR或EAR),其POM和任何附加构件(来源、javadoc等)所产生的一个特定的项目。
(8). maven-dependency-plugin:
maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列表dependency:tree能进一步的描绘项目依赖树,dependency:analyze可以告诉你项目依赖潜在的问题,如果你有直接使用到的却未声明的依赖
,该目标就会发出警告。maven-dependency-plugin还有很多目标帮助你操作依赖文件,例如dependency:copy-dependencies能将项目依赖从本地Maven仓库复制到某个特定的文件夹下面。


数据库

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CREATE TABLE `user` (  
  2.   `id` int(10) NOT NULL auto_increment,  
  3.   `name` varchar(30default NULL,  
  4.   `age` int(3default NULL,  
  5.   PRIMARY KEY  (`id`)  
  6. )  

applicationContext-dataSource.xml

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"  
  2.       init-method="init" destroy-method="close">  
  3.       <property name="url" value="jdbc:mysql://localhost:3306/test2" />  
  4.       <property name="username" value="root" />  
  5.       <property name="password" value="123" />  
  6.       <property name="initialSize" value="1" />  
  7.       <property name="maxActive" value="20" />  
  8.   </bean>  

数据源,druid连接池的简单配置

applicationContext-hibernate.xml


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <import resource="applicationContext-dataSource.xml" />  
  2.   
  3.     <bean id="sessionFactory"  
  4.         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
  5.         <property name="dataSource" ref="dataSource" />  
  6.         <property name="packagesToScan" value="com.entity" /><!--自动扫描指定的包下面注解的实体类,也就是User类 -->  
  7.         <property name="hibernateProperties">  
  8.             <props>  
  9.                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
  10.                 <prop key="hibernate.show_sql">true</prop>  
  11.                 <prop key="hibernate.format_sql">false</prop>  
  12.                 <prop key="hibernate.use_sql_comments">false</prop>  
  13.                 <prop key="hibernate.cache.use_second_level_cache">false</prop>  
  14.             </props>  
  15.         </property>  
  16.     </bean>  
  17.     <!-- start spring集中式声明 -->  
  18.     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  19.         <tx:attributes>  
  20.             <tx:method name="saveUser*" />  
  21.             <tx:method name="saveUserThrowException*" rollback-for="Exception"/>  
  22.             <tx:method name="findUsers*" <span style="font-family: Arial, Helvetica, sans-serif;">read-only="true"</span><span style="font-family: Arial, Helvetica, sans-serif;">/></span>  
  23.              <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到session-->    
  24.             <tx:method name="*"  propagation="REQUIRED" />  
  25.         </tx:attributes>  
  26.     </tx:advice>  
  27.       
  28.     <aop:config>  
  29.         <aop:pointcut id="productServiceMethods" expression="execution(* com.service..*.*(..))"/>  
  30.         <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" />  
  31.     </aop:config>  
  32.     <!-- spring集中式声明 -->  
  33.       
  34.     <bean id="userService" class="com.service.impl.UserService">  
  35.         <property name="userDao">  
  36.             <bean class="com.dao.impl.UserDaoImpl">  
  37.                 <property name="sessionFactory" ref="sessionFactory"></property>  
  38.             </bean>  
  39.         </property>  
  40.     </bean>  
  41.     <!-- 事务管理器 -->  
  42.     <bean id="transactionManager"  
  43.         class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
  44.         <property name="sessionFactory" ref="sessionFactory" />  
  45.     </bean>  

下面我们来看看这个配置文件各个参数的作用吧!
1).<import resource="applicationContext-dataSource.xml" />导入数据源
2).<bean id="sessionFactory"
class=" org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" /> <!--把dataSource链接进来-->
<property name="packagesToScan" value="com.entity" /> <!--自动扫描指定的包下面注解的实体类,也就是User类 -->
<property name="hibernateProperties"> <!--配置hibernate的属性-->
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <!--定义mysql方言-->
<prop key="hibernate.show_sql">true</prop> <!--输出所有SQL语句到控制台-->
<prop key="hibernate.format_sql">false</prop> <!--在log和console中打印出更漂亮的SQL-->
<prop key="hibernate.use_sql_comments">false</prop> <!--如果开启, Hibernate将在SQL中生成有助于调试的注释信息-->
<prop key="hibernate.cache.use_second_level_cache">false</prop> <!--能用来完全禁止使用二级缓存. 对那些在类的映射定义中指定<cache>的类,会默认开启二级缓存-->
</props>
</property>
</bean>
3).<!-- start spring集中式声明 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="saveUser*" />
<tx:method name="saveUserThrowException*" rollback-for="Exception"/>
<tx:method name="findUsers*"  read-only="true"/>
<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到session--> 
<tx:method name="*"  propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="productServiceMethods" expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" />
</aop:config>
<!-- spring集中式声明 -->
集中式声明也就是采用AOP的方式,进行拦截式声明
我们再来了解下expression的表达式作用:
* com.service..*.*(..)
第一个*代表所有的返回值类型
第二个*代表所有的类
第三个*代表类所有方法
最后一个(..)代表所有的参数。
service.. 意思是:service包或者子包
service. 意思是:service包
再来了解下网上给的常见的例子:我再详细解释下
  • 任意公共方法的执行:大概意思是符合 public *(所有返回值)  *(所有方法名)  (..)(所有的参数)
  • execution(public * *(..))
  • 任何一个以“set”开始的方法的执行:*(所有返回值) set*(所有名) (..)(所有的参数)
  • execution(* set*(..))
  • AccountService 接口的任意方法的执行:*(所有返回值) .*(所有方法名) (..)(所有的参数)
  • execution(* com.xyz.service.AccountService.*(..))
  • 定义在service包里的任意方法的执行:*(所有返回值) .*(service包下的所有类)  .*(所有方法名)  (..)(所有的参数)
  • execution(* com.xyz.service.*.*(..))
  • 定义在service包或者子包里的任意类的任意方法的执行:*(所有返回值)  ..*(service包或子包下的所有类)   .*(所有方法名)  (..)(所有的参数)
  • execution(* com.xyz.service..*.*(..))

4).<bean id="userService" class="com.service.impl.UserService">
<property name="userDao">
<bean class="com.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</property>
</bean>
把dao注入到service中而没有采用,注解的方式自动装载
5). <!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
这个不用多说了吧!一个事务的管理器

至此集中式声明就配置完毕啦!!
下面再来看看dao service test吧!

IUserDao.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public interface IUserDao {  
  2.     public void save(User user);  
  3.     public List<User> query(String sql,Object[] args);  
  4. }  

UserDaoImpl.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class UserDaoImpl extends AbstractHibernateDao<User> implements IUserDao {  
  2.   
  3.     public UserDaoImpl() {  
  4.         super(User.class);  
  5.     }  
  6. }  
这块其实写的就是为了更灵活一些,把想要查询的实体一改就可以换成另一种实体的查询,而不用改具体实现的代码,对于这种常用的方法调用,可以防止方法的冗余,真的很不错啊!

AbstractHibernateDao.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public abstract class AbstractHibernateDao <E extends Serializable>{  
  2.     private Class<E> entityClass;  
  3.     private SessionFactory sessionFactory;  
  4.        
  5.     protected AbstractHibernateDao(Class<E> entityClass) {  
  6.         this.entityClass = entityClass;  
  7.     }  
  8.    
  9.     public Session getCurrentSession() {  
  10.         return sessionFactory.getCurrentSession();  
  11.     }  
  12.    
  13.     public E findById(Serializable id) {  
  14.         return (E) getCurrentSession().get(entityClass, id);  
  15.     }  
  16.    
  17.     public void save(E e) {  
  18.         getCurrentSession().save(e);  
  19.     }  
  20.    
  21.     public void delete(E e) {  
  22.         getCurrentSession().delete(e);  
  23.     }  
  24.    
  25.     public List<E> query(String hql, Object[] args) {  
  26.         Query query=getCurrentSession().createQuery(hql);  
  27.         if(args!=null){  
  28.             for (int i = 0; i < args.length; i++) {  
  29.                 query.setParameter(i, args[i]);  
  30.             }  
  31.         }  
  32.         return query.list();  
  33.     }  
  34.   
  35.     public Class<E> getEntityClass() {  
  36.         return entityClass;  
  37.     }  
  38.   
  39.     public void setEntityClass(Class<E> entityClass) {  
  40.         this.entityClass = entityClass;  
  41.     }  
  42.   
  43.     public SessionFactory getSessionFactory() {  
  44.         return sessionFactory;  
  45.     }  
  46.   
  47.     public void setSessionFactory(SessionFactory sessionFactory) {  
  48.         this.sessionFactory = sessionFactory;  
  49.     }  
  50.   
  51.      
  52. }  

User.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @Entity  
  2. @Table(name="user")  
  3. public class User implements Serializable{  
  4.     private static final long serialVersionUID = 1724315528421427938L;  
  5.       
  6.     @Id  
  7.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
  8.     @Column(name = "id", nullable = false)     
  9.     private Long id;  
  10.     @Column(name="name",nullable=true,length=25)  
  11.     private String name;  
  12.     @Column(name="age",nullable=true)  
  13.     private Integer age;  
  14.    ........  
  15.     set...  
  16.     get...  
  17.    ........  
  18.     @Override  
  19.     public String toString() {  
  20.         return "User [id=" + id + ", name=" + name + ", age=" + age + "]";  
  21.     }  
  22. }  

IUserService.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public interface IUserService {  
  2.     void saveUser();  
  3.     void saveUserThrowException() throws Exception;  
  4.     void findUsers();  
  5. }  

UserService.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class UserService implements IUserService{  
  2.     private IUserDao userDao;  
  3.     public IUserDao getUserDao() {  
  4.         return userDao;  
  5.     }  
  6.     public void setUserDao(IUserDao userDao) {  
  7.         this.userDao = userDao;  
  8.     }  
  9.     public void saveUser() {  
  10.         User u1=new User();  
  11.         u1.setName("邵");  
  12.         u1.setAge(24);  
  13.         userDao.save(u1);  
  14.   
  15.         User u2=new User();  
  16.         u2.setName("陈");  
  17.         u2.setAge(20);  
  18.         userDao.save(u2);  
  19.     }  
  20.     public void saveUserThrowException() throws Exception {  
  21.         User u1=new User();  
  22.         u1.setName("邵");  
  23.         u1.setAge(24);  
  24.         userDao.save(u1);     
  25.         if(1+1>1){  
  26.             throw new Exception("Runtime error...");//抛出一般的异常:Exception  
  27.         }      
  28.         User u2=new User();  
  29.         u2.setName("陈");  
  30.         u2.setAge(20);  
  31.         userDao.save(u2);        
  32.     }  
  33.     public void findUsers() {  
  34.         List<User> users=userDao.query("from User where name=?"new Object[]{"邵"});  
  35.         for (User user : users) {  
  36.             System.out.println(user);  
  37.         }  
  38.     }   
  39. }  

SpringHibernateTest.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class SpringHibernateTest {  
  2.     private static ApplicationContext ctx = null;  
  3.   
  4.     @BeforeClass   
  5.     public static void onlyOnce() {  
  6.          ctx = new ClassPathXmlApplicationContext("applicationContext-hibernate.xml");  
  7.     }  
  8.     @Test  
  9.     public void testSave(){  
  10.         IUserService service=ctx.getBean("userService",IUserService.class);  
  11.         service.saveUser();  
  12.     }  
  13.       
  14. //    @Test  
  15.     public void testSaveThrowException() throws Exception{  
  16.         IUserService service=ctx.getBean("userService",IUserService.class);  
  17.         service.saveUserThrowException();  
  18.     }   
  19.     @Test  
  20.     public void testJDBCDaoQuery(){  
  21.         IUserService service=ctx.getBean("userService",IUserService.class);  
  22.         service.findUsers();  
  23.     }  
  24. }  

注解式事务管理:

applicationContext-dataSource.xml

与上面声明式事务一样的配置

applicationContext-hibernate.xml

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <import resource="applicationContext-dataSource.xml" />  
  2.   
  3.    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
  4.        <property name="dataSource" ref="dataSource" />  
  5.        <property name="packagesToScan" value="com.entity" />  
  6.        <property name="hibernateProperties">  
  7.            <props>  
  8.                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
  9.                <prop key="hibernate.show_sql">true</prop>  
  10.                <prop key="hibernate.format_sql">false</prop>  
  11.                <prop key="hibernate.use_sql_comments">false</prop>  
  12.                <prop key="hibernate.cache.use_second_level_cache">false</prop>  
  13.            </props>  
  14.        </property>  
  15.    </bean>  
  16.      
  17.    <bean id="userService" class="com.service.impl.UserService">  
  18.        <property name="userDao">  
  19.            <bean class="com.dao.impl.UserDaoImpl">  
  20.                <property name="sessionFactory" ref="sessionFactory"></property>  
  21.            </bean>  
  22.        </property>  
  23.    </bean>  
  24.   
  25.    <!-- 事务管理器 -->    
  26.    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">    
  27.        <property name="sessionFactory" ref="sessionFactory"/>    
  28.    </bean>   
  29.      
  30.    <tx:annotation-driven transaction-manager="transactionManager"/><!--启动注解用注解来管理事务-->  

 <tx:annotation-driven transaction-manager="transactionManager"/> 它是注解配置事务的关键

AbstractHibernateDao、UserDaoImpl、IUserDao、User、IUserService的配置与声明式事务一样的配置

不一样的地方:

UserService.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @Transactional//默认propagation=Propagation.REQUIRED所以不像集中式声明那样都要配置  
  2. public class UserService implements IUserService{  
  3.     private IUserDao userDao;  
  4.   
  5.     public void saveUser() {  
  6.         User u1=new User();  
  7.         u1.setName("邵");  
  8.         u1.setAge(24);  
  9.         userDao.save(u1);  
  10.           
  11.         //测试时,可以添加此异常,或去掉异常,测试Spring对事物的管理  
  12. //        if(1+1>1){  
  13. //            throw new RuntimeException("Runtime error...");//抛出运行时异常:RuntimeException  
  14. //        }  
  15.           
  16.         User u2=new User();  
  17.         u2.setName("陈");  
  18.         u2.setAge(20);  
  19.         userDao.save(u2);  
  20.     }  
  21.   
  22.     @Transactional(rollbackFor={Exception.class})  
  23.     public void saveUserThrowException() throws Exception {  
  24.         User u1=new User();  
  25.         u1.setName("邵");  
  26.         u1.setAge(24);  
  27.         userDao.save(u1);  
  28.           
  29.         if(1+1>1){  
  30.             throw new Exception("Runtime error...");//抛出一般的异常:Exception  
  31.         }  
  32.           
  33.         User u2=new User();  
  34.         u2.setName("陈");  
  35.         u2.setAge(20);  
  36.         userDao.save(u2);  
  37.           
  38.     }  
  39.       
  40.     @Transactional(readOnly=true)   
  41.     public void findUsers() {  
  42.         List<User> users=userDao.query("from User where name=?"new Object[]{"邵"});  
  43.         for (User user : users) {  
  44.             System.out.println(user);  
  45.         }  
  46.     }  
  47.       
  48.     public IUserDao getUserDao() {  
  49.         return userDao;  
  50.     }  
  51.     public void setUserDao(IUserDao userDao) {  
  52.         this.userDao = userDao;  
  53.     }  
  54. }  

@Transactional//默认propagation=Propagation.REQUIRED所以不像集中式声明那样都要配置
@Transactional(readOnly=true) readOnly=true表明所注解的方法或类只是读取数据。
                                                    readOnly=false表明所注解的方法或类是增加,删除,修改数据。



注解与XML配置的区别

注解:是一种分散式的元数据,与源代码紧绑定。

xml:是一种集中式的元数据,与源代码无绑定。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值