• Spring MVC+Spring +Hibernate配置事务,但是事务不起作用


    最近做项目,被一个问题烦恼了很久。使用Spring MVC+Spring +Hibernate开发项目,在使用注解配置事务管理,刚开始发现无论如何数据库都无法更新,但是可以从数据库查询到数据。怀疑是配置文件的问题,但是反复确认,配置文件没有问题。后来将注解配置事务变更为注解配置事务,同样无法入库。

    后来在dao层方法里面添加了session.flush()数据可以入库,但是不能回滚。正常的情况下,配置事务成功的话,事务会自动提交,session会自动flush。于是怀疑配置的事务根本就没有起到作用。在网上查找资料,终于发现问题症结所在。

    引起问题原因:spring初始化时优先component-scan bean,注入Web Controller 的Service直接拿了上下文中的@Service("someService"),这个时候@Transactional (readOnly=false, isolation = Isolation.READ_COMMITTED) 还没有被处理.所以Web Controller 的Service是SomeServiceImpl而不是AOP的$ProxyNO.

    解决途径:不让spring扫描到ServiceImpl类,直接写在xml文件,其它的配置和annotation照用,这样事务就起作用了.

    按照上述配置,发现事务起作用了,自动提交,并且在出现异常的时候自动回滚。

    工程具体配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation
    ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SMS</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:school-spring-*.xml</param-value> </context-param> <listener> <!-- 负责加载spring的配置文件 --> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 直接使用spring的encodingFilter--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping> <!-- 集成使用Spring MVC --> <servlet> <servlet-name>defaultDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!-- Spring XML 文件 --> <param-value>classpath*:school-springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>defaultDispatcher</servlet-name> <url-pattern>/school/*</url-pattern> </servlet-mapping> <!-- 验证码生成 --> <servlet> <servlet-name>image_code</servlet-name> <servlet-class>cn.com.yinuo.common.web.util.RandomCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>image_code</servlet-name> <url-pattern>/imgCode</url-pattern> </servlet-mapping> <!-- 解决hibernate延迟加载问题 --> <!-- <filter> <filter-name>openSession</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSession</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> --> <!-- session超时定义,单位为分钟 --> <session-config> <session-timeout>30</session-timeout> </session-config> <!-- 欢迎界面 --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

    web.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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation=
                "http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                http://www.springframework.org/schema/jee 
                http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">
                            
        <!-- Spring管理配置文件 -->
        <bean id="propertyConfigurer"
            class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath*:school_config.properties</value>
                </list>
            </property>
            <!-- 可注入中文 -->
            <property name="fileEncoding" value="UTF-8"/>
        </bean>
        
        <!-- 注解扫描包  会扫描school包下面所有的类文件以及包  待确认-->
        <context:component-scan base-package="cn.com.yinuo.school">
            <context:exclude-filter type="regex" expression="cn.com.yinuo.*.web.*"/>
            <context:exclude-filter type="regex" expression=".*ServiceImpl$" />
        </context:component-scan>
        
        <!-- 配置multipartResolver处理器 -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="utf-8" />
            <property name="maxUploadSize" value="10485760000" />
            <property name="maxInMemorySize" value="40960" />
        </bean>
       <bean name="informationService" class="cn.com.yinuo.school.InformationMaintenance.biz.service.impl.InformationServiceImpl">
        </bean>
    </beans>

    school-spring-core.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:p="http://www.springframework.org/schema/p"
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:jee="http://www.springframework.org/schema/jee"
        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.2.xsd
                http://www.springframework.org/schema/mvc 
                http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                http://www.springframework.org/schema/jee 
                http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
                            
        <!-- 注解扫描包  会扫描school包下面所有的类文件以及包  待确认-->
        <context:component-scan base-package="cn.com.yinuo.school">
            <!-- <context:include-filter type="regex" expression="cn.com.yinuo.*.web.*"/> -->
        </context:component-scan>
        <!-- 开启注解 -->
        <mvc:annotation-driven/>
        <!-- 上面开启注解的方式是下面开启注解方式的优化,下面的方式在3之后就过时了 -->
        <!--  
            <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
            <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
         -->
        <!-- 访问静态资源   -->
        <mvc:resources location="/js/" mapping="/js/**"/>
        <mvc:resources location="/img/" mapping="/img/**"/>
        <mvc:resources location="/css/" mapping="/css/**"/>
        
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </beans>

    school-springmvc.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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:jee="http://www.springframework.org/schema/jee"
        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.2.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                http://www.springframework.org/schema/jee 
                http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
        <!-- Spring管理 Hibernate -->
            <!-- 配置DataSource -->
        <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}"/>
            <property name="initialSize" value="${initialSize}"/>
            <property name="maxActive" value="${maxActive}"/>
            <property name="maxIdle" value="${maxIdle}"/>
            <property name="minIdle" value="${minIdle}"/>
        </bean>
        
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="packagesToScan">
                <list>
                    <value>cn.com.yinuo.school.model.domain</value>
                </list>
            </property>
            <property name="mappingResources">
              <list>
                <value>../resources/${resource.mapping.sql}</value>
              </list>
            </property>
            <property name="hibernateProperties">
              <props>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                    <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                    <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                      <!-- 
                      <prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop>
                       -->  
                    <prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="Hibernate.current_session_context_class">thread</prop>
                    <prop key="hibernate.cache.use_query_cache">false</prop>
                    <prop key="hibernate.connection.release_mode">after_transaction</prop>
                </props>
            </property>
        </bean>
        
        <bean id="transactionManager"
              class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
        
        <context:annotation-config/>
        
        <aop:aspectj-autoproxy proxy-target-class="true"/> 
        
        <aop:config proxy-target-class="true">  
        </aop:config> 
         <!--  注解配置事务-->
        <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
     
        <!-- 
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="Exception" />
                <tx:method name="update*" propagation="REQUIRED" read-only="false"/>
                <tx:method name="insert*" propagation="REQUIRED" read-only="false"/>
                <tx:method name="modify*" propagation="REQUIRED" read-only="false"/>
                <tx:method name="delete*" propagation="REQUIRED" read-only="false"/>
                <tx:method name="get*" propagation="REQUIRED" />
                <tx:method name="save*" propagation="REQUIRED" read-only="false"/>
            </tx:attributes>
        </tx:advice>
       
        <aop:config>
            <aop:pointcut id="interceptorPointCuts"
                expression="execution(* cn.com.yinuo.school.InformationMaintenance.biz.service.impl.InformationServiceImpl.*(..))" />
            <aop:advisor advice-ref="txAdvice"
                pointcut-ref="interceptorPointCuts" />       
        </aop:config>      
     -->
    </beans>

    school-spring-hibernate.xml

    package cn.com.yinuo.school.InformationMaintenance.web;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import net.sf.json.JSONObject;
    
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import cn.com.yinuo.school.InformationMaintenance.biz.service.InformationService;
    import cn.com.yinuo.school.model.domain.Student;
    import cn.com.yinuo.school.util.Json;
    
    @Controller
    @RequestMapping("/information")
    public class InformationController {
        @Autowired
        private InformationService informationService;
        
        private static Logger logger=Logger.getLogger(InformationController.class);
        
        @RequestMapping("/toRegister")
        public String toRegister(){
            return "JSP/imformation/register";
        }
        @RequestMapping("/addUser")
        public Json addUser(HttpServletRequest request,HttpServletResponse response){
            Student student=new Student();
            student.setName("阿享");
            student.setClassId("001001");
            student.setCreditId("4365671235678931");
            student.setMailBox("591137758@qq.com");
            student.setGender(0);
            student.setPassword("janeyloveachris");
            student.setType(1);
            informationService.addUser(student);
            Json json=new Json();
            json.setSuccess(true);
            json.setMsg("新增成功");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter pw=null;
            JSONObject jsonObject =JSONObject.fromObject(json);
            try {
                pw=response.getWriter();
                pw.append(jsonObject.toString());
                logger.debug("返回到前台的对象是"+jsonObject.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(pw!=null){
                    pw.close();
                }
            }
            return null;
        }
    }

    InformationController.java

    package cn.com.yinuo.school.InformationMaintenance.biz.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import cn.com.yinuo.school.InformationMaintenance.biz.dao.InformationDao;
    import cn.com.yinuo.school.InformationMaintenance.biz.service.InformationService;
    
    @Transactional
    @Service
    public class InformationServiceImpl implements InformationService {
    
        @Autowired
        private InformationDao informationDao;
    
        @Transactional(propagation=Propagation.REQUIRED,rollbackFor=java.lang.Exception.class,readOnly=false)
        @Override
        public void addUser(Object object) {
            informationDao.addUser(object);
        }
    
        @Override
        public Object getAllUsers() {
            return informationDao.getAllUsers();
        }
    
    }

    InformationServiceImpl.java

    package cn.com.yinuo.school.InformationMaintenance.biz.dao.impl;
    
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Repository;
    
    import cn.com.yinuo.school.InformationMaintenance.biz.dao.InformationDao;
    import cn.com.yinuo.school.model.domain.Student;
    import cn.com.yinuo.school.model.domain.Teacher;
    
    @Repository
    public class InformationDaoImpl /*extends HibernateDaoSupport */implements InformationDao {
    
        @Autowired
        private SessionFactory sessionFactory;
        
        private Logger logger=LoggerFactory.getLogger(InformationDaoImpl.class);
    
        @Override
        public void addUser(Object object) {
            /*Session session=sessionFactory.openSession();
            Transaction tc=session.beginTransaction();*/
            Session session=sessionFactory.getCurrentSession();
            //tc.begin();
            if(object instanceof Student){
                //getHibernateTemplate().save((Student)object);
                //sessionFactory.getCurrentSession().save((Student)object);
                session.saveOrUpdate((Student)object);
            }else if(object instanceof Teacher){
                //getHibernateTemplate().save((Teacher)object);
                session.save((Teacher)object);
            }
            //tc.commit();
            //session.flush();
            System.out.println((1/0));
        }
    
        @Override
        public Object getAllUsers() {
            //super.getHibernateTemplate().find("");
            Student st=new Student();
            Query query=sessionFactory.openSession().createQuery("from "+st.getClass().getName());
            logger.debug(query.getQueryString());
            return query.list();
        }
    
    }

    InformationDaoImpl.java

    后来师父找到了我的问题所在:在springmvc.xml在扫描包的时候缺少了:use-default-filters="false"

     

    <context:component-scan base-package="cn.com.yinuo.school" use-default-filters="false" >
            <context:include-filter type="regex" expression="cn.com.yinuo.*.web.*Controller$"/> 
        </context:component-scan>

     

    添加之后,去掉spring-core.xml中的

    <context:component-scan base-package="cn.com.yinuo.school">
            <context:exclude-filter type="regex" expression="cn.com.yinuo.*.web.*Controller$"/>
            <!-- <context:exclude-filter type="regex" expression=".*ServiceImpl$" /> -->
        </context:component-scan>

    以及service的配置执行发现事务同样起到作用了。

    去掉我的其他配置,同时不加use-default-filters="false",会报错 session没有绑定。

    师父参照的博客文章地址:http://blog.csdn.net/shuwei003/article/details/7281792

     

  • 相关阅读:
    简单对称加密
    temp
    标点符号
    PHP定时执行计划任务
    从杨致远辞去雅虎说起,那些衰落的网站巨头给我们的启示
    JS判断手机浏览器
    如何制作在线参考手册
    不是每个程序员都是适合创业,即使你工作了十年
    两级导航栏联动效果
    关于腾讯ip接口一个流传很广的错误用法
  • 原文地址:https://www.cnblogs.com/loveyixiang/p/4446615.html
Copyright © 2020-2023  润新知