Spring Transaction的三种配置方式

<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- 如果使用@Transactional方式管理事务,虚做如下声明。
        transaction-manager可以省略,前提是有id为transactionManager的Bean
        同时,需要在需要用到事务管理方法的上面做如下声明:
        @Transactional(propagation=Propagation.REQUIRED, //事务传播
            isolation=Isolation.READ_COMMITTED, //事务隔离
            rollbackFor=IOException.class, //回滚事务
            noRollbackFor=IllegalStateException.class,
            timeout=30, //设置超时
            readOnly=false) //设置只读属性
     -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!-- Transaction manager for a single hibernate SessionFactory -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <!--
    事务传播行为(propagation):
    REQUIRED 如果有事务在运行,当前的方法就在这个事务内部运行,否则,就启动一个新的事务,并让他在自己的事务内运行
    REQUIRED_NEW 当前的方法必须开启新事务,并在他自己的事务中运行,如果有事务在运行,应将他挂起(suspend)
    SUPPORTS 如果有事务在运行,当前的方法就运行在这个事务中,否则,他可以不运行在事务中
    NOT_SUPPORTED 当前的方法不应该在事务内运行,如果有运行中的事务,就挂起他
    MANDATORY 当前的方法必须运行在事务中,如果没有正在运行的事务,就抛出异常
    NEVER 当前的方法不应该在事务中运行,如果当前存在事务,就抛出异常
    NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。否则,他就启动一个新的事务,并在他自己的事务内部运行
     -->
    <!--
    事务的隔离级别(isolation)
    DEFAULT 使用底层数据库的默认隔离级别,对于大多数数据库来说默认隔离级别都是READ_COMMITTED
    READ_UMCOMMITTED 允许事务读取未被其他事务提交的变更。脏读、不可重复读和幻读都有可能发生
    READ_COMMITTED 只允许事务读取已经被其他事务提交的变更。可以避免脏读问题,但不可重复读和幻读仍可能出现
    REPEATABLE——READ 确保事务可以多次从一个字段中读取相同的值。
    在这个事务持续期间,禁止其他事务对这个字段进行更新。可以避免脏读和不可重复读,但仍可能出现幻读
    SERIALIZABLE 确保事务可以多次从一个表中读取相同的行。
    在这个事务执行期间,禁止其他事务对该表执行插入、更新和删除操作。所有并发性问题都可以避免,但是性能十分低下
     -->

    <!-- 事务通知模式
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*DAO" propagation="REQUIRED" isolation="DEFAULT"
                rollback-for="java.io.IOException" no-rollback-for="java.lang.IllegalStateException"
                timeout="30" read-only="false" />
            <tx:method name="insert" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
     -->
    <!-- 用事务通知声明式的管理事务 -->
    <!--
    <aop:config>
        <aop:pointcut id="baseService" expression="execution(* org.jhat.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="baseService" order="1"/>
    </aop:config>
     -->
    <!-- Spring AOP 模式
    <bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="target" ref="userDAO" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="insert">
                    PROPAGATION_REQUIRED,
                    ISOLATION_DEFAULT,
                    -java.io.IOException,+java.lang.IllegalStateException,
                    timeout_30,readOnly
                </prop>
            </props>
        </property>
    </bean>
     -->

</beans>

Spring AOP

Spring AOP编程,具体的代理类,如果只是需要在被代理的对象执行之前运行,那么只需实现 org.springframework.aop.MethodBeforeAdvice 接口,做相应的处理即可,而 org.springframework.aop.AfterReturningAdviceorg.springframework.aop.ThrowsAdvice 则分别用于实现方法调用返回后和抛出异常后的代理接口。当然,还可以通过实现 org.aopalliance.intercept.MethodInterceptor 接口,轻松实现上诉三个功能。但需要注意的是,用代理之后,那么被代理的对象执行完之后返回的结果不在是原有的类型,而变成了被代理对象所实现的接口类,即变成了基类的对象,所以在传参时需要额外注意。同理,若果需要给某个类加上代理,也需要将这个类进行一次抽象,让其实现某一接口。

Read More ...

Spring日志问题

用Spring AOP做日志记录,给userAction加上日志之后就始终报错

Struts has detected an unhandled exception:
    Messages:java.lang.NullPointerException
    File:org/apache/struts2/components/UIBean.java
    Line number:792
    
    Stacktraces
    org.apache.jasper.JasperException: java.lang.NullPointerException
    java.lang.NullPointerException
 
 2010-11-24 17:51:54,862 ERROR (com.opensymphony.xwork2.config.providers.InterceptorBuilder:38) - Actual exception
 Caught Exception while registering Interceptor class org.jhat.interceptor.BasicInterceptor - interceptor - file:/E:/Program/Tomcat/webapps/jhat/WEB-INF/classes/struts-user.xml:10:86
 Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type '$Proxy5 implementing org.jhat.service.UserService,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.jhat.service.impl.UserServiceImpl' for property 'userService'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy5 implementing org.jhat.service.UserService,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.jhat.service.impl.UserServiceImpl] for property 'userService': no matching editors or conversion strategy found
 Caused by: java.lang.IllegalStateException: Cannot convert value of type [$Proxy5 implementing org.jhat.service.UserService,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.jhat.service.impl.UserServiceImpl] for property 'userService': no matching editors or conversion strategy found

大概猜出来是因为类型转换出错,但是给userDAO加上日志却没有报错,而且还能正常记录日志,那么就不应该是类型转换的问题。最后查源代码发现,原来UserAction中的setUserService()方法接受的参数是UserServiceImple类型,我想经过日志代理之后,返回的是向上转型的UserService类型的对象,所以参数类型不一致,最终导致报错,最后将setUserService()方法接受的参数类型改为UserService,再次运行一切正常……

从这一点来看,接口编程模式的确带来了不少好处,实现该接口的类所产生的对象都可以向上转型为接口类型的对象,所以有效地降低了对象之间的耦合度。同时也该注意的是,构造对象时尽量用接口或基类,再用不同的实现类或子类实例化。

食堂阿姨太好了

今晚去芙蓉餐厅改善伙食,打完饭回来悲剧的发现书包上遗留了某个哥们的菜汤,当时哭的心都有了……

这时候一位阿姨走过来,说:”同学,刚才看见一个同学不小心把菜汤撒你书包上了,我帮你擦一下。“当时那个叫感动啊……然后看个阿姨帮我擦书包,除了说谢谢还是只有说谢谢。本以为,阿姨用抹布擦完就好了,没想到,阿姨又拿出一张餐巾纸,继续擦……再次感动,阿姨是在是太好了。

MyEclipse整合SSH

1. 准备工作

1.1. 软件准备及安装

JDK1.6.0_20 (>1.5)
Apache Tomcat/6.0.26 (>5.x)
MySQL 5.1.51-community (>5.x)
MyEclipse 8.6 for Spring (版本关系不大,版本越高,只是开发越方便)
Read More ...