本文基于SPRING2.56,HIBERANTE3.25及Oracle10g classes14.jar驱动,介绍SPRING与HIBERNATE是如何配合的细节,如SESSION、 事务、数据库连接何时打开与关闭;如果调用不是发自请求,不经过FILTER(如定时器对SERVICE调用),如何做到从头到尾只用一个SESSION? 此时SESSION需不需要手动关闭?从SESSION取得的数据库连接需不需要关闭, 看完本文,你会清楚里面每一个细节。
两种访问系统的路径:
1、request-->filters(spring and struts)-->actions-->AOP(transaction)-->services-->dao-->db
2、timer(run)->AOP(transaction)-->services-->dao-->db
下面是调用链的图示
在WEB.XML配置了OpenSessionInViewFilter,整个请求只用一个SESSION,
在ACTION与SERVICE之间使用SPRING的AOP配置事务拦截器,所以事务范围涵盖整个SERVICE的方法调用,
DAO中一般使用SPRING的HibernateTemplate对象操作数据库
首先看OpenSessionInViewFilter在web.xml和事务拦截器相关配置
Xml代码
复制代码
- <!--web.xml-->
- <filter>
- <filter-name>openSessionInViewFilter</filter-name>
- <filter-class>
- org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
- </filter-class>
- <init-param>
- <param-name>singleSession</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
-
- /////SRPING配置文件中事务拦截器相关配置
- <!-- hibernate 事务管理者 -->
- <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory"></property>
- </bean>
- <!-- hibernate 事务拦截器 -->
- <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
- <!-- 注入事务管理者 -->
- <property name="transactionManager" ref="transactionManager" />
- <property name="transactionAttributes">
- <!-- 定义事务属性-->
- <props>
- <prop key="*">PROPAGATION_REQUIRED</prop>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="add*">PROPAGATION_REQUIRED</prop>
- <prop key="save*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="noTran*">PROPAGATION_NOT_SUPPORTED,readOnly</prop>
- </props>
- </property>
- </bean>
- /////配置service自动代理
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <property name="beanNames">
- <!-- 代理所有Service -->
- <list>
- <value>*Service</value>
- </list>
- </property>
- <property name="interceptorNames">
- <list>
- <value>transactionInterceptor</value>
- </list>
- </property>
- </bean>
|
//下面从FILTER开始分析代码
Java代码
复制代码
- //这是OpenSessionInViewFilter类的方法,请求到来时,此方法由父类OncePerRequestFilter的doFilter()方法调用,
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
-
- //取得SessionFactory实例,实际上就是调用WebApplicationContext.getBean("beanName"),
- SessionFactory sessionFactory = lookupSessionFactory(request);
- //在lookupSessionFactory方法里看到原来此FILTER还支持配置sessionFactory为的名字,默认就叫sessionFactory,如果想改成其它名字具体配置方式:
- //在web.xml中,<init-param><param-name>sessionFactoryBeanName</param-name><param-value>sessionFactory</param-value></init-param>
-
- //此次调用有无打开SESSION,有的话在finally块关闭
- boolean participate = false;
- //是否单SESSION模式(上文web.xml中配置了),注意这并不意味着每个请求只用一个connection,下文详解
- if (isSingleSession()) {//这里我只分析单SESSION的情况,因为另一种情况不是此filter推荐的用法,就懒得看了
- // 单SESSION模式
-
- // 是否已经打开了SESSION,一般来说每个请求一开始是没有打开的,除非在打开SESSION之后进行forward跳转并再次被拦截
- if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
- participate = true;
- }
- else {
- logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
- //打开session,注意想在整个请求内部都用SESSION,这一句还不够,还必须有下面一句。getSession方法如何打开SESSION接下来讲解
- Session session = getSession(sessionFactory);
- //把SESSION放入SessionHolder,再用sessionFactory作为KEY,SessionHolder作为VALUE放入MAP,再把此MAP放入ThreadLocal
- //------不熟ThreadLocal看这,其他人跳过,ThreadLocal有两个主要的方法,get()和set(value),用法和MAP差不多,只是不需要提供KEY,
- //KEY就是当前线程,这样对于每个线程,只能往ThreadLocal里放入一个对象,在此放入了一个MAP。
- //不同的线程可以同时操作这个ThreadLocal对象,放入内容,因为各自有着不同的KEY------//
- TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
- }
- }
- else {//非单Session模式,本文不讨论此情况
- // deferred close mode
- if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
- // Do not modify deferred close: just set the participate flag.
- participate = true;
- }else {
- SessionFactoryUtils.initDeferredClose(sessionFactory);
- }
- }
-
- try {//SESSION已打开,往下调用,-->action-->aop-->service-->dao-->db
- filterChain.doFilter(request, response);
- }
-
- finally {//目标调用完成,关闭SESSION
- if (!participate) {//如果上文打开了SESSION
- if (isSingleSession()) {
- //从ThreadLocal里面把上面放入的MAP移除
- SessionHolder sessionHolder =
- (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
- logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
- //关闭SESSION
- closeSession(sessionHolder.getSession(), sessionFactory);
- }
- else {
- // deferred close mode
- SessionFactoryUtils.processDeferredClose(sessionFactory);
- }
- }
- }
- }
|
getSession方法
Java代码
复制代码
- //OpenSessionInViewFilter类,还是上面那个FILTER类
- protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
- //取SESSION,下文讲解
- Session session = SessionFactoryUtils.getSession(sessionFactory, true);
- //设置提交方式,getFlushMode默认返回FlushMode.NEVER,
- //NEVER看名字好像是永不提交,其实是外部显式调用FLUSH时才提交的意思,也许是因为名字不好,此变量已过时了,新的名字是FlushMode.MANUAL
- //如果请求是写操作,会在打开事务时被改成AUTO,
- FlushMode flushMode = getFlushMode();
- if (flushMode != null) {
- session.setFlushMode(flushMode);
- }
- return session;
- }
|
SessionFactoryUtils.doGetSession方法
Java代码
复制代码
- //SessionFactoryUtils类,取SESSION,此工具方法在以下两种情况被调用:在FILTER层开SESSION和在DAO层取SESSION去查数据库
- //在FILTER层调用时,没有事务(执行此方法的后半部份),在DAO层调用时,由于经过了AOP,开启了事务(执行方法的前半部份)
- //在没有JTA事务的环境中,此方法只是打开或取得一个SESSION,关于事务的事什么也没有做。
- private static Session doGetSession(
- SessionFactory sessionFactory, Interceptor entityInterceptor,
- SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
- throws HibernateException, IllegalStateException {
-
- Assert.notNull(sessionFactory, "No SessionFactory specified");
- //上文放入的sessionHolder在这里被取出来,如果调用来源于FILTER,则还没有放入,取出空,如果DAO层的调用,那么就不为空了
- SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
- ///--------------前半部份-------------------//////////////
- if (sessionHolder != null && !sessionHolder.isEmpty()) {// DAO中的调用,取得非空值,
- Session session = null;
-
- //如果:事务是否已开始 && sessionHolder中没有SESSION或只有一个默认SESSION
- if (TransactionSynchronizationManager.isSynchronizationActive() &&
- sessionHolder.doesNotHoldNonDefaultSession()) {
- //取出SESSION,里面主要判断一下SESSION有没有被关闭
- session = sessionHolder.getValidatedSession();
- //session不为空 && 事务没有开始,
- if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
- //在AOP中开始事务时,会将这个标志设为真,所以这里不会被执行,至少我还没有发现哪一次执行经过这里了
- logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
- TransactionSynchronizationManager.registerSynchronization(//注册一个SESSION
- new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
- sessionHolder.setSynchronizedWithTransaction(true);
- // 取出当前SESSION的提交方式
- FlushMode flushMode = session.getFlushMode();
- if (flushMode.lessThan(FlushMode.COMMIT) &&
- !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
- //如果是小于COMMIT,就是NEVER,那么改成自动
- session.setFlushMode(FlushMode.AUTO);
- //设置之前的提交模式
- sessionHolder.setPreviousFlushMode(flushMode);
- }
- }
- }
- else {//这里也是一般都不会被执行,因为AOP中已经开启了事务
- // No Spring transaction management active -> try JTA transaction synchronization.
- session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
- }
- if (session != null) {
- return session;
- }
- }
- ////////-------------------后半部份--------------------------
-
- //来自FILTER的调用,一般sessionHolder为空(同一请求forward后被再次拦截就不会空,执行不到这里),
- logger.debug("Opening Hibernate Session");
- //调用HIBERNATE打开SESSION
- Session session = (entityInterceptor != null ?
- sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());
-
- // 当前请求是否已开启事务,FILTER中的调用,还没有到AOP层,事务没有打开,一般会执行ELSE
- if (TransactionSynchronizationManager.isSynchronizationActive()) {
- // We're within a Spring-managed transaction, possibly from JtaTransactionManager.
- logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
- SessionHolder holderToUse = sessionHolder;
- if (holderToUse == null) {
- holderToUse = new SessionHolder(session);
- }
- else {
- holderToUse.addSession(session);
- }
- if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
- session.setFlushMode(FlushMode.NEVER);
- }
- TransactionSynchronizationManager.registerSynchronization(
- new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
- holderToUse.setSynchronizedWithTransaction(true);
- if (holderToUse != sessionHolder) {
- TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
- }
- }
- else {
- // 上面没有找到事务,从sessionFactory中找,如果sessionFactory有配置JTA事务,则注册事务
- // 本文也没有配置JTA事务,所以里面什么也没有干,还是没有注册事务
- registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
- }
-
- // 如果不自动创建 && sessionHolder中没有session,则关闭SESSION
- if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
- closeSession(session);
- throw new IllegalStateException("No Hibernate Session bound to thread, " +
- "and configuration does not allow creation of non-transactional one here");
- }
- //到此就在FILTER中取得了(或者说打开了)SESSION,下面就从ACTION调用SERVICE这一节了。
- return session;
- }
|
//下面开始到了ACTION的操作,action调用service,此service实际上是Spring动态生成的代理类,此代理类调用
//目标SERVICE类对应的方法前,要经过AOP拦截,下面我们对ACTION到SERVICE这中间经过的所有类方法代码分析一遍。
//我的应用在AOP层配置了一个事务拦截器,所以这中间的代码主要操作事务相关。
//动态生成的代理类代码看不到,从动态代理类下面的那个类(JdkDynamicAopProxy)开始吧
Java代码
复制代码
- //JdkDynamicAopProxy类,此方法被动态代理类调用
- //参数说明:proxy动态代理类对象,method目标方法,args目标方法参数
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- MethodInvocation invocation = null;
- Object oldProxy = null;
- boolean setProxyContext = false;
-
- //targetSource对象包含目标SERVICE对象
- TargetSource targetSource = this.advised.targetSource;
- Class targetClass = null;
- Object target = null;
-
- try {
- //如果目标类没有重载equals方法 && 目前正在调用目标类的equals方法,那直接调本类重载方法,
- //这样就不需要再往下走,不需要再开启事务等等多余的操作以至于浪费性能了,下面的几个IF都是做类似的事
- if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
- // The target does not implement the equals(Object) method itself.
- return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE);
- }
- if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
- // The target does not implement the hashCode() method itself.
- return new Integer(hashCode());
- }
- if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
- method.getDeclaringClass().isAssignableFrom(Advised.class)) {
- // Service invocations on ProxyConfig with the proxy config...
- return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
- }
-
- Object retVal = null;
-
- //ProxyConfig类的exposeProxy属性,表示是否要将当前的代理对象放入AopContext中,
- //这样在你的Service中可以用AopContext.currentProxy()取得当前代理,相当于this引用,
- //不同于this引用的是,调用当前代理会被AOP拦截,而this不会。
- //此属性默认为FALSE,如果要打开,
- //在BeanNameAutoProxyCreator等代理类BEAN的配置中加入<property name="exposeProxy" value="true" />
- if (this.advised.exposeProxy) {
- // Make invocation available if necessary.
- oldProxy = AopContext.setCurrentProxy(proxy);
- setProxyContext = true;
- }
-
- // 取得目标(真实SERVICE对象)
- target = targetSource.getTarget();
- if (target != null) {
- targetClass = target.getClass();
- }
-
- // 取得所有拦截器
- List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
-
- // 如果没有拦截器
- if (chain.isEmpty()) {
- // 直接调用目标
- retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
- }
- else {//有拦截器
- // 创建一个调用器对象
- invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
- // 通过调用器往下调用目标或第一个拦截器
- retVal = invocation.proceed();
- }
-
- // 调用的返回结果目标类对象本身,就把它替换成代理类对象
- if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&
- !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
- retVal = proxy;
- }
- return retVal;
- }
- finally {//释放资源
- //主要是从当前线程清除代理类对象
- if (target != null && !targetSource.isStatic()) {
- targetSource.releaseTarget(target);
- }
- if (setProxyContext) {
- // Restore old proxy.
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
|
递归调用拦截器
Java代码
复制代码
- //ReflectiveMethodInvocation类,上面执行retVal = invocation.proceed();就进入到了这个方法
- //这个方法主要是递归调用各个拦截器,最后调用目标类
- public Object proceed() throws Throwable {
- // 判断是否还有拦截器要调用,
- if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
- //没有拦截器了,调用目标
- return invokeJoinpoint();
- }
-
- //取出拦截器
- Object interceptorOrInterceptionAdvice =
- this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
-
- //判断拦截器型,对不同类型的调用方法不一样,SPRING事务拦截器TransactionInterceptor是MethodInterceptor实现类,
- //不属于InterceptorAndDynamicMethodMatcher,执行ELSE
- if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
- InterceptorAndDynamicMethodMatcher dm =
- (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
- if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
- return dm.interceptor.invoke(this);
- }
- else {//方法匹配失败,跳过,继续递归
- return proceed();
- }
- }
- else {
- // 调用事务拦截器等,MethodInterceptor--林信良的SPRING手册介绍过个这接口如何使用
- return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
- }
- }
|
事务拦截器
Java代码
复制代码
- //TransactionInterceptor--SPRING的事务拦截器实现类,这个方法可以根据事务管理器的种类分类if和else上下两部分,
- //如果配置的是org.springframework.orm.hibernate3.HibernateTransactionManager等非CallbackPreferringPlatformTransactionManager接口实现类
- //则看只需要看if部份
- //了解这里工作原理很重要:
- //1、如果是请求发起的调用,流程路线为--FILTER打开Session,并且绑定到了线程信息中(TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session))),
- //在此方法里标志为旧SESSION,开始事务,调用目标,提交或回滚事务,判断如果是旧SESSION,则事务结束释放连接但不关闭SESSION,如果还用此SESSION再开启事务,再绑定另外的连接(所以上文说单SESSION并不等于同一个连接),最后在FILTER关闭SESSION。
- //2、如果不是请求发起的调用,如计划任务Timer.schedule(...)发起的SERVICE调用,流程为--在此方法打开SESSION,标志为新连接,开启事务,调用目标,提交或回滚事务,释放数据库连接,判断如果是新SESSION,则关闭SESSION。
- //总结如下:
- //1、只要有配置了此事务拦截器,底层使用SPRING的HibernateTemplate.getSession()或其提供的各种查询,那么SESSION和数据库连接的关闭不需要你操心。
- //2、如果要在Timer的run方法中多次调用SERVICE时,也要实现OpenSessionInViewFilter这样的效果,那么使用如这句,结束时要记得自已关闭SESSION。
- //打开SESSION后:TransactionSynchronizationManager.bindResource(getSessionFactory(), new SessionHolder(session));
- //最后关闭SESSION:
- //SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
- //SessionFactoryUtils.closeSession(sessionHolder.getSession());
- public Object invoke(final MethodInvocation invocation) throws Throwable {
- // 取得目标类名
- Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);
-
- // 通过类名及方法名,取得事务属性,即<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>这些内容
- final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
- //取得类名+方法名全称
- final String joinpointIdentification = methodIdentification(invocation.getMethod());
- //没有事务属性 || 事务管理者不是CallbackPreferringPlatformTransactionManager类型(事务采用回调方法实现的方式)
- if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
- //开始事务并创建事务信息对象(此对象主要包括事务属性和事务状态等信息),就是在这里调用了session.beginTransaction()方法
- //将事务信息以当前线程为KEY放入了TransactionAspectSupport.transactionInfoHolder对象中
- //注意:到这里如果当前取得到SessionHolder,那么SESSION就被标记成老SESSION,提交事务时就不会关闭之,反之那么session会在打开,并被标为新SESSION,提交事务时会把此SESSION关闭
- TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
- Object retVal = null;
- try {
- // 调用下一下拦截器,如果没有下一个拦截器,那么目标类会被调用
- retVal = invocation.proceed();
- }
- catch (Throwable ex) {
- // 发生异常时,在这里回滚,回滚时,除了rollBack,还执行session.clear(),setFlushMode(NEVER)等动作
- // 新SESSION会在此被关闭,老的则不会
- completeTransactionAfterThrowing(txInfo, ex);
- throw ex;
- }
- finally {
- //清理当前线程对应的事务信息,
- cleanupTransactionInfo(txInfo);
- }
- //未发生异常,提交事务,如果是新SESSION,会在此被关闭,老的则不会
- commitTransactionAfterReturning(txInfo);
- return retVal;
- }
-
- else {
- // 回调式的事务管理器,SPRING中只提供了一个WebSphereUowTransactionManager的具体实现,
- /**CallbackPreferringPlatformTransactionManager接口的注释
- * Extension of the {@link org.springframework.transaction.PlatformTransactionManager}
- * interface, exposing a method for executing a given callback within a transaction.
- * <p>Implementors of this interface automatically express a preference for
- * callbacks over programmatic <code>getTransaction</code>, <code>commit</code>
- * and <code>rollback</code> calls. Calling code may check whether a given
- * transaction manager implements this interface to choose to prepare a
- * callback instead of explicit transaction demarcation control.*/
- // 大意应该是可以由此接口的具体实现来决定事务的控制,我的E文一般般,有错的就砸砖
- try {
- Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
- new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
- TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
- try {
- //往下调用
- return invocation.proceed();
- }
- catch (Throwable ex) {
- if (txAttr.rollbackOn(ex)) {
- // A RuntimeException: will lead to a rollback.
- if (ex instanceof RuntimeException) {
- throw (RuntimeException) ex;
- }
- else {
- throw new ThrowableHolderException(ex);
- }
- }
- else {
- // A normal return value: will lead to a commit.
- return new ThrowableHolder(ex);
- }
- }
- finally {
- cleanupTransactionInfo(txInfo);
- }
- }
- });
-
- // Check result: It might indicate a Throwable to rethrow.
- if (result instanceof ThrowableHolder) {
- throw ((ThrowableHolder) result).getThrowable();
- }
- else {
- return result;
- }
- }
- catch (ThrowableHolderException ex) {
- throw ex.getCause();
- }
- }
- }
|
分享到:
相关推荐
spring声明式事务实例 可复制修改使用。。。。。。。。。。
Spring 声明式事务处理 Spring 中的事务处理可以分为两种方式:声明式事务处理和编程式事务处理。声明式事务处理通过 AOP 的实现,把事务管理代码作为方面封装到业务代码中,使得事务管理代码和业务代码解藕。这...
文件名为`Spring声明式事务处理-1.mht`到`Spring声明式事务处理-5.mht`,通过阅读这些文件,你将能够深入理解Spring声明式事务处理的各个方面,包括配置、使用场景、最佳实践以及常见问题的解决方法。
在这个"spring声明式事务处理demo"中,我们将探讨如何在MyEclipse环境下实现这一功能。 首先,我们要理解Spring事务管理的两种主要方式:编程式事务管理和声明式事务管理。编程式事务管理通常通过AOP(面向切面编程...
Spring声明式事务配置管理方法
在"spring声明式事务管理配置方式"中,主要涉及到以下几个关键知识点: 1. **Spring事务管理器(Transaction Manager)**: - Spring支持多种事务管理器,如DataSourceTransactionManager(用于JDBC事务)和...
### 标题解读:Spring声明式事务配置 Spring框架提供了两种主要类型的事务管理方式:编程式事务管理和声明式事务管理。声明式事务管理通过XML配置或注解的形式定义事务边界,使得业务逻辑与事务控制分离。 ### ...
本文将深入探讨Spring声明式事务的实现机制、优缺点以及如何在实际项目中进行配置和使用。 1. **声明式事务管理概述** 声明式事务管理与编程式事务管理相对,后者需要开发者在代码中显式调用开始、提交、回滚等...
Spring 声明式事务和Spring 编程式事务
《Spring Boot多数据源(支持Spring声明式事务切换和回滚)》 Spring Boot多数据源技术是构建高效、灵活的多租户SaaS架构的关键。在本文中,我们将深入探讨如何实现动态数据源切换,支持Spring声明式事务管理,并讨论...
1. **配置Spring声明式事务**: 在Spring中,声明式事务管理依赖于AOP(面向切面编程)来实现。首先,需要配置一个事务管理器,通常使用`DataSourceTransactionManager`,它与数据源`dataSource`关联。然后,通过`...
Spring 声明式事务处理与多数据源支持 在大部分涉及到数据库操作的项目里面,事务控制、事务处理都是一个无法回避的问题。Spring 框架提供了声明式事务处理机制,使得业务代码中进行事务控制操作起来非常简单。只需...
Spring声明式事务管理是Spring框架中的一个重要特性,它允许开发者在不修改代码的情况下,通过配置来控制事务的边界。这种方式极大地简化了事务管理,使得事务处理与业务逻辑解耦,提高了代码的可维护性和可测试性。...
本资料包"spring声明式事务管理+jdbc+连接池.zip"显然是针对Spring框架在数据库操作方面的深入学习,特别是如何利用Spring进行声明式事务管理和JDBC操作,以及如何配置和使用数据库连接池。接下来,我们将详细探讨这...
Spring声明式事务是Java开发中不可或缺的一部分,它利用Spring的AOP(面向切面编程)和代理机制,为开发者提供了一种简洁的方式来管理事务。在本文中,我们将深入探讨Spring声明式事务的工作原理,源码分析,以及...
### Spring声明式事务管理异常处理测试与总结 #### 背景介绍 Spring框架作为Java企业级应用领域中最重要的框架之一,提供了强大的依赖注入(DI)功能和面向切面编程(AOP)支持,同时也提供了丰富的事务管理机制。...
本文主要探讨Spring声明式事务管理的配置,这是Spring提供的一种简便的事务管理方式,允许开发者在不编写任何事务管理代码的情况下实现事务控制。这种方式极大地提高了代码的可维护性和可读性。 首先,我们要理解...
1.本例子的使用了 ssh 框架 2.本例子DAO层 使用了 getHibernateTemplate 来实现数据的新增修改和删除 3.本例子使用了声明式...4.本例子提供了详细的使用方法,可以根据 readme.txt 来逐步的验证声明式事务是否起作用
一、Spring声明式事务管理 1. **什么是事务**:事务是数据库操作的基本单元,它保证了数据的一致性和完整性。一个事务中的所有操作要么全部成功,要么全部失败。 2. **事务特性**:事务通常遵循ACID原则,即原子性...