关于spring中配置hibernate申明事务无效的有关问题
关于spring中配置hibernate申明事务无效的问题
在spring配置hibernate的申明事务的时候,发现事务控制一直都不好使,关键配置如下:
spring的MVC的配置如下:
applicationContext.xml的配置如下:
在以上配置的情况下,无论我的service怎么配置@Transactional注解,都无效,如:
即使我在removeContact方法中添加只读控制readOnly = true,相关删除实体操作一样能够正常执行。
后面在网上搜了一些信息,问题在于spring在实例化@Controller类时,Spring会自动把关联的@Service(此@Service已做了@Transaction事务注解)类实例化,此时事务并未生效,导致@Transaction注解无效,事务未被注册。解决办法如下:
将spring的mvc配置中的以下信息:
修改为:
表示容器在使用注解加载控制层时,不实例化控制层以外的组件。
除此以外,也将applicationContext.xml文件中添加如下的配置:
意思就是说使用注解加载除控制层以外的组件,这时,在加载service层时事务就会关联在服务层上,相关的事务注解的配置也就生效了。
在spring配置hibernate的申明事务的时候,发现事务控制一直都不好使,关键配置如下:
spring的MVC的配置如下:
<context:component-scan base-package="com.going"/> <context:annotation-config /> <!-- To enable @RequestMapping process on type level and method level --> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="marshallingConverter" /> <ref bean="jsonConverter" /> <ref bean="atomConverter" /> </list> </property> </bean> <!-- XML Converter --> <bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxbMarshaller" /> <property name="supportedMediaTypes" value="application/xml" /> </bean> <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.going.sample.domain.Employee</value> <value>com.going.sample.domain.EmployeeList</value> </list> </property> </bean> <!-- JSON Converter --> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes" value="application/json" /> </bean> <!-- ATOM Converter --> <bean id="atomConverter" class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"> <property name="supportedMediaTypes" value="application/atom+xml" /> </bean> <!-- Client --> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <ref bean="marshallingConverter" /> <ref bean="jsonConverter" /> <ref bean="atomConverter" /> </list> </property> </bean> <!-- viewer --> <!-- xmlView --> <bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg ref="jaxbMarshaller" /> </bean> <!-- jsonView --> <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> <entry key="html" value="text/html" /> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/view/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> </bean>
applicationContext.xml的配置如下:
<!-- 数据源的配置 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <!-- hibernate工厂类的配置 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation"> <value>classpath:hibernate.cfg.xml</value> </property> <property name="configurationClass"> <value>org.hibernate.cfg.AnnotationConfiguration</value> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${jdbc.dialect}</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.jdbc.fetch_size">25</prop> <prop key="hibernate.jdbc.batch_size">50</prop> <!-- dev --> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.generate_statistic">false</prop> <!-- cache --> <!--代表是否使用查询缓存,这里不使用,因为一般而言查询缓存的命中率并不是很高,所以我们没有 必要为每一个用户的查询缓存它的数据,所以这里设为false--> <prop key="hibernate.cache.use_query_cache">false</prop> <!--代表使用Hibernate的二级缓存--> <prop key="hibernate.cache.use_second_level_cache">false</prop> <!-- create db table --> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
在以上配置的情况下,无论我的service怎么配置@Transactional注解,都无效,如:
@Service @Transactional public class ContactServiceImpl implements ContactService { @Autowired private ContactRepository contactRepository; public ContactRepository getContactRepository() { return contactRepository; } public void setContactRepository(ContactRepository contactRepository) { this.contactRepository = contactRepository; } @Transactional(propagation=Propagation.REQUIRED) public void addContact(Contact contact) { contactRepository.addContact(contact); } public List<Contact> listContact() { return contactRepository.listContact(); } @Transactional(readOnly = true) public void removeContact(String id) { contactRepository.removeContact(id); } }
即使我在removeContact方法中添加只读控制readOnly = true,相关删除实体操作一样能够正常执行。
后面在网上搜了一些信息,问题在于spring在实例化@Controller类时,Spring会自动把关联的@Service(此@Service已做了@Transaction事务注解)类实例化,此时事务并未生效,导致@Transaction注解无效,事务未被注册。解决办法如下:
将spring的mvc配置中的以下信息:
<context:component-scan base-package="com.going" />
修改为:
<context:component-scan base-package="com.going"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan>
表示容器在使用注解加载控制层时,不实例化控制层以外的组件。
除此以外,也将applicationContext.xml文件中添加如下的配置:
<context:component-scan base-package="com.going"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
意思就是说使用注解加载除控制层以外的组件,这时,在加载service层时事务就会关联在服务层上,相关的事务注解的配置也就生效了。