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 ...
随机推荐
- UIView的 形变属性transform
// ViewController.m // 形变属性transform // // Created by LiuWei on 2018/4/23. // Copyright © 2018年 xxx. ...
- 【Linux】批量结束某一脚本的进程
ps -ef | grep **.sh |grep -v grep | awk '{print $2}' | xargs kill -9
- [POJ3735]Training little cats
题目:Training little cats 链接:http://poj.org/problem?id=3735 分析: 1)将操作用矩阵表示出来,然后快速幂优化. 2)初始矩阵:$ \left[ ...
- 软件-Axure:Axure RP
ylbtech-软件-Axure:Axure RP Axure RP是一款专业的快速原型设计工具.Axure(发音:Ack-sure),代表美国Axure公司:RP则是Rapid Prototypin ...
- DCloud-MUI-JS:相关摘录
ylbtech-DCloud-MUI-JS:相关摘录 1.返回顶部 1.JS initFun: function() { var oldBack = mui.back; mui.back = func ...
- flask扩展系列之 - 访问速度限制
flask-limiter 是一个对客户端的访问速率进行限制的flask扩展.可以自定义一些访问的(速度)限制条件来把那些触发限制的请求拒之门外.一般常用来进行对爬虫的限制. 下面就常见的用法,举了一 ...
- chromedriver安装报错
解决方法: 可以使用 npm init -f命令生成package.json,package.json中缺少的字段可以参照模板 package.json进行填充,package.json中的字段 ...
- 关于函数lower_bound()如何使用的问题
这个函数是c++ STL里自带的函数,应该需要引用头文件#include<iostream> 功能:在一个有序的序列中查找可以将value(一个变量)放在队列里面而不会引起序列长度变化,单 ...
- python自带的split VS numpy中的split比较
Python split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串 str1.split() 里面的参数,可以是空格,逗号,字符串啥的,具体应用与 ...
- poj1426 Find The Multiple (DFS)
题目: Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41845 Accepted: ...