Spring框架-经典的案例和demo,一些可以直接用于生产,使用atomikos来处理多数据源的一致性事务等
Spring Examples
Demo website:http://www.ityouknow.com/
对Spring框架的学习,包括一些经典的案例和demo,一些可以直接用于生产。
spring4-mybatis3-simple:spring4+mybatis3的增删改查的例子
spring-mybatis-mulidatasource:对mybaits的简单封装,方便简单的调用和多数据源的配置
spring-mybatis-mulidatasource-atomikos: 使用atomikos来处理多数据源的一致性事务
spring-jedis-simple: 封装对redis的增删改查以及对象的操作
spring-jedis-cluster:利用spring封装了对redis集群的操作
spring-fastdsf:Spring 和 FastDFS集群操作的示例。
atomikos官网:https://www.atomikos.com/Documentation/SpringIntegration
spring 多数据源配置
spring 多数据源配置一般有两种方案:
1、在spring项目启动的时候直接配置两个不同的数据源,不同的sessionFactory。在dao 层根据不同业务自行选择使用哪个数据源的session来操作。
2、配置多个不同的数据源,使用一个sessionFactory,在业务逻辑使用的时候自动切换到不同的数据源,有一个种是在拦截器里面根据不同的业务现切换到不同的datasource;有的会在业务层根据业务来自动切换。但这种方案在多线程并发的时候会出现一些问题,需要使用threadlocal等技术来实现多线程竞争切换数据源的问题。
【本文暂时只讨论第一种方案】
spring多事务配置主要体现在db配置这块,配置不同的数据源和不同的session
1、一下贴出 spring-db.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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <bean id="test1DataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="driverClassName" value="${database.test1.driverClassName}" />
<property name="url" value="${database.test1.url}" />
<property name="username" value="${database.test1.username}" />
<property name="password" value="${database.test1.password}" />
</bean> <bean id="test2DataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="driverClassName" value="${database.test2.driverClassName}" />
<property name="url" value="${database.test2.url}" />
<property name="username" value="${database.test2.username}" />
<property name="password" value="${database.test2.password}" />
</bean> <bean id="test1SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="test1DataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean> <bean id="test2SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="test2DataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean> <bean id="test1TxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="test1DataSource"></property>
</bean>
<bean id="test2TxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="test2DataSource"></property>
</bean> <tx:annotation-driven transaction-manager="test2TxManager" />
<tx:annotation-driven transaction-manager="test1TxManager" /> </beans>

2、dao层做了一个小的封装,将不同的SqlSessionFactory 注入到 SessionFactory,通过BaseDao来做简单的封装,封装不同库的基本增删改。dao实现层都集成于Basedao 这样的话,实现可以根据自己需要来选择不同的库来操作不同的内容。
session工厂

package com.neo.dao;
import com.neo.entity.Entity;
public class BaseDao extends SessionFactory{
public void test1Update(Entity entity) {
this.getTest1Session().update(entity.getClass().getSimpleName()+".update", entity);
}
public void test2Update(Entity entity) {
this.getTest2Session().update(entity.getClass().getSimpleName()+".update", entity);
}
}

BaseDao

package com.neo.dao;
import com.neo.entity.Entity;
public class BaseDao extends SessionFactory{
public void test1Update(Entity entity) {
this.getTest1Session().update(entity.getClass().getSimpleName()+".update", entity);
}
public void test2Update(Entity entity) {
this.getTest2Session().update(entity.getClass().getSimpleName()+".update", entity);
}
}

以上的配置在多数据源连接,正常的增删改都是没有问题的,但是遇到分布式的事务是就出问题:
测试代码:

package com.neo.service.impl; import javax.annotation.Resource; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.neo.dao.UserDao;
import com.neo.dao.UserInformationsDao;
import com.neo.entity.UserEntity;
import com.neo.entity.UserInformationsEntity;
import com.neo.service.UserService; @Service
public class UserServiceImpl implements UserService { @Resource UserDao userDao;
@Resource UserInformationsDao userInformationsDao; @Override
@Transactional
public void updateUserinfo() { UserEntity user=new UserEntity();
user.setId(1);
user.setUserName("李四4"); UserInformationsEntity userInfo=new UserInformationsEntity();
userInfo.setUserId(1);
userInfo.setAddress("陕西4"); userDao.updateUser(user);
userInformationsDao.updateUserInformations(userInfo); if(true){
throw new RuntimeException("test tx ");
}
} }

在service添加事务后,更新完毕抛出异常,test2更新进行了回滚,test1 数据更新没有回滚。
解决方案添加分布式的事务,Atomikos和spring结合来处理。
Atomikos多数据源的配置

<?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:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <bean id="test1DataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="test1"/>
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="xaProperties">
<props>
<prop key="url">${database.test1.url}</prop>
<prop key="user">${database.test1.username}</prop>
<prop key="password">${database.test1.password}</prop>
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean> <bean id="test2DataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="test2"/>
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="xaProperties">
<props>
<prop key="url">${database.test2.url}</prop>
<prop key="user">${database.test2.username}</prop>
<prop key="password">${database.test2.password}</prop>
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean> <bean id="test1SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="test1DataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean> <bean id="test2SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="test2DataSource" />
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml" />
</bean> <!-- 分布式事务 -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="true"/>
</bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300"/>
</bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager"/>
<property name="userTransaction" ref="atomikosUserTransaction"/>
</bean> <tx:annotation-driven/> </beans>
Spring框架-经典的案例和demo,一些可以直接用于生产,使用atomikos来处理多数据源的一致性事务等的更多相关文章
- SpringMVC_05 利用spring框架来处理异常
待更新... 2017年5月13日22:46:52 1 用spring框架来处理异常 将异常抛给spring框架,让spring框架来处理 异常:这样就不需要程序员去捕获异常啦 2 方法一:配置简单异 ...
- Spring框架 JdbcTemplate类 @Junit单元测试,可以让方法独立执行 如:@Test
package cn.zmh.PingCe; import org.junit.Test; import org.springframework.jdbc.core.BeanPropertyRowMa ...
- spring框架学习笔记7:事务管理及案例
Spring提供了一套管理项目中的事务的机制 以前写过一篇简单的介绍事务的随笔:http://www.cnblogs.com/xuyiqing/p/8430214.html 还有一篇Hibernate ...
- Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例
前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...
- spring框架和junit框架结合使用案例
package ltssh; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.be ...
- Maven+Spring+Hibernate+Shiro+Mysql简单的demo框架(二)
然后是项目下的文件:完整的项目请看 上一篇 Maven+Spring+Hibernate+Shiro+Mysql简单的demo框架(一) 项目下的springmvc-servlet.xml配置文件: ...
- 学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在
Spring框架最核心东西便是大名鼎鼎的IoC容器,主要通过DI技术实现.下面我通过Demo的演变过程,对比学习耦合性代码,以及解耦和的过程,并深入理解面向接口编程的真正内涵. 这个例子包括如下几个类 ...
- Spring 框架基础(03):核心思想 IOC 说明,案例演示
本文源码:GitHub·点这里 || GitEE·点这里 一.IOC控制反转 1.IOC容器思想 Java系统中对象耦合关系十分复杂,系统的各模块之间依赖,微服务模块之间的相互调用请求,都是这个道理. ...
- Spring框架加案例
依赖: <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependenc ...
随机推荐
- Struts第一个程序。
1:创建完程序后.先写web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmln ...
- vue开发微信公众号--开发准备
由于工作项目的原因,需要使用vue开发微信公众号,但是这种微信公众号更多是将APP套了一个微信的壳子,除了前面的授权和微信有关系以外,其他的都和微信没多大的关系了,特此记录 开发流程 首先需要在电脑上 ...
- css 图片 和 文本 的处理
图片 1.css3已经可以实现 img标签 和 img内图片分开处理的功能了.类似标签的背景图. https://www.zhangxinxu.com/wordpress/2015/03/css3 ...
- 26 October in 614
Practice tower 有 \(N\,(2\le N\le 600000)\) 块砖,要搭一个 \(N\) 层的塔,要求:如果砖 \(A\) 在砖 \(B\) 上面,那么 \(A\) 不能比 \ ...
- handler消息机制入门
handler消息机制入门 为什么要用handle? 我们在网络上读取图片信息时,是不能把耗时操作放在主线程里面的,当我们在子线程中获取到了图片的消息的时候,我们就需要把这个数据传给主线程. 而直接使 ...
- TypeScript:TypeScript 百科
ylbtech-TypeScript:TypeScript 百科 TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类 ...
- Mac定时执行脚本_服务launchctl
Mac 设置自动执行定时任务, 步骤: 1. 编写plist 2.将plist放入该目录下 ~/Library/LaunchAgents 3.命令启动 添加: launchctl load /Syst ...
- 使用Python的PIL模块来进行图片对比
使用Python的PIL模块来进行图片对比 在使用google或者baidu搜图的时候会发现有一个图片颜色选项,感觉非常有意思,有人可能会想这肯定是人为的去划分的,呵呵,有这种可能,但是估计人会累死, ...
- [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent c ...
- 面试题57:数组中2个数的和(也是leetcode题目)
题目:给定一个整数数列,找出其中和为特定值的那两个数. 你可以假设每个输入都只会有一种答案,同样的元素不能被重用. 示例: 给定 nums = [2, 7, 11, 15], target = 9 因 ...