springmvcspring mybatis数据源 有多个数据源,可以用注解实现bean的声明吗

您所在的IP地址对ITeye网站访问过于频繁,为了判断您的访问是真实用户,请您填写验证码,谢谢!Spring(11)
原文地址:
此篇文章是基于Spring3.0和mybatis3.2的
总体大概流程:
1. 拷贝所需jar
2.写一个数据库切换的工具类:DataSourceContextHolder,用来切换数据库
3.写一个DynamicDataSource类来继承AbstractRoutingDataSource,并重写determineCurrentLookupKey()方法,来达到动态切换数据库
4. 创建springmvc-servlet.xml文件,然后创建spring配置文件(beans.xml)
5. 在beans.xml文件中配置数据源。我这里配置的三个数据源
6. 在beans.xml文件中创建sqlSessionFactory实例
7. 在beans.xml文件中配置事物、事物的传播性
8. 在beans.xml文件中配置AOP
9. 创建一个User对象,配置User.xml文件。写一个UserMapper接口,用来操作User对象的接口
10. 将User类的路径以及User.xml文件的路径在mybatis-config.xml文件中配置
11. 写一个UserService接口(接口里面的方法和UserMapper接口里面的方法一致,返回值和参数可不同,方法名最好一致),并写UserServiceImpl来实现UserService接口
12.写Controller类,并在其中写相对应的方法,给外部调用
下面看一下我的工程的目录:
common包存放的是一些公用类
controller包下放的是提供给外部访问的接口的(.do)类
datasource包下是用来配置数据库
entity:实体类
mapper:.....存放XXMapper以及实体类的对应表的关系的xml文件
下面一步步的来讲解:
1、拷贝jar文件。需要的jar文件入下图所示,因为我的项目中用到了json解析,所以导入了json相关的包
2.写一个数据库切换的工具类:DataSourceContextHolder,用来切换数据库
public class DataSourceContextHolder {
private static final ThreadLocal&String& contextHolder = new ThreadLocal&String&();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
public static String getDbType() {
return ((String) contextHolder.get());
public static void clearDbType() {
contextHolder.remove();
3.写一个DynamicDataSource类来继承AbstractRoutingDataSource,并重写determineCurrentLookupKey()方法,来达到动态切换数据库
import java.sql.SQLFeatureNotSupportedE
import java.util.logging.L
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataS
public class DynamicDataSource extends AbstractRoutingDataSource {
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder. getDbType();
4. 创建springmvc-servlet.xml文件,然后创建spring配置文件(beans.xml),看一下我的springmvc-servlet.xml文件。
& &这里配置了一个注解扫描器,一般填自己的主包名就可以了,他会自动扫描我的com.baimi.routerweb包下面所有的带注解的类或者方法,常变量等。
& &还配置了一个视图解析器(如果需要用到jsp文件,就需要配置此解析器)
& &最后引入我的spring的配置文件:beans.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:mvc= &http://www.springframework.org/schema/mvc&
xsi:schemaLocation= &http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd&&
&!-- 注解扫描器 --&
&context:component-scan base-package =&com.baimi.routerweb&/&
&!-- 配置试图解析器 --&
&bean class= &org.springframework.web.servlet.view.InternalResourceViewResolver& &
&property name =&prefix& value=&/&&&/ property&
&property name =&suffix& value=&.jsp&&&/ property&
&import resource =&classpath:beans.xml&/&
5. 在beans.xml文件中配置数据源。我这里配置的三个数据源,不过在配置数据源之前,先配置一下注解扫描器。然后我接着配置了三个数据源,然后配置动态数据源
&context:component-scan base-package =&com& /&
&!-- 多数据源配置 --&
&bean id =&ds_admin& class= &mons.dbcp.BasicDataSource& &
&property name =&driverClassName& value= &com.mysql.jdbc.Driver&&&/property &
&property name =&url& value= &jdbc:mysql://192.168.19.72:msh_admin& &&/property &
&property name =&username& value=&root&&&/ property&
&property name =&password& value=&root&&&/ property&
&bean id =&ds_partner& class= &mons.dbcp.BasicDataSource& &
&property name =&driverClassName& value= &com.mysql.jdbc.Driver&&&/property &
&property name =&url&
value= &jdbc:mysql://192.168.19.72:msh_partner& &&/property &
&property name =&username& value=&root&&&/ property&
&property name =&password& value=&root&&&/ property&
&bean id =&ds_mop& class=&mons.dbcp.BasicDataSource&&
&property name =&driverClassName& value= &com.mysql.jdbc.Driver&&&/property &
&property name =&url& value= &jdbc:mysql://192.168.19.72:msh_mop& &&/property &
&property name =&username& value=&root&&&/ property&
&property name =&password& value=&root&&&/ property&
&!-- 动态配置数据源 --&
&bean id =&dataSource& class= &com.baimi.routerweb.datasource.DynamicDataSource& &
&property name =&targetDataSources&&
&map key-type =&java.lang.String&&
&entry value-ref =&ds_admin& key= &ds_admin&&&/entry &
&entry value-ref =&ds_partner& key= &ds_partner&&&/entry &
&entry value-ref =&ds_mop& key=&ds_mop&&&/ entry&
&/property &
&property name =&defaultTargetDataSource& ref= &ds_mop&&&/property &
&!-- 默认使用ds1的数据源 --&
6. 在beans.xml文件中创建sqlSessionFactory实例
&!-- 创建SqlSessionFactory --&
&bean id =&sqlSessionFactoryBean& class= &org.mybatis.spring.SqlSessionFactoryBean& &
&!-- 指定数据源 --&
&property name =&dataSource& ref=&dataSource& /&
&!-- 指定mybatis 的配置文件 --&
&property name =&configLocation& value= &classpath:mybatis-config.xml& /&
7. 在beans.xml文件中配置事物、事物的传播性
&!-- 配置事务 --&
&bean id =&transactionManager&
class= &org.springframework.jdbc.datasource.DataSourceTransactionManager& &
&property name =&dataSource& ref=&dataSource&&&/ property&
&!-- 映射接口 --&
&bean class =&org.mybatis.spring.mapper.MapperScannerConfigurer&&
&property name =&basePackage& value= &com.baimi.routerweb.mapper&&&/property &
&!-- 配置事务的传播特性 --&
&tx:advice id =&txAdvice& transaction-manager=&transactionManager&&
&tx:attributes &
&tx:method name =&find*& read-only=&true& /&
&tx:method name =&get*& read-only=&true& /&
&tx:method name =&query*& read-only=&true& /&
&tx:method name =&add*& propagation=&REQUIRED& /&
&tx:method name =&update*& propagation=&REQUIRED& /&
&tx:method name =&del*& propagation=&REQUIRED& /&
&/tx:attributes &
&/tx:advice &
在beans.xml文件中配置AOP,注意这里,expression&后面一定要是自己程序所在包名,复制的时候一定要改掉
&!-- 配置AOP --&
&aop:config &
&!-- 切点 --&
&aop:pointcut expression =&execution(* com.baimi.routerweb.service..*.*(..))&
id= &pointcut& /&
&aop:advisor advice-ref =&txAdvice& pointcut-ref=&pointcut& /&
&/aop:config &
9. 创建一个User对象,配置User.xml文件。写一个UserMapper接口,用来操作User对象的接口。
& & User类属性有点长,请忽略这些属性
public class User {
private int userId;
private int compId;
private String euserN
private String euserP
private int euserS
private String eAddT
private String eLeaveT
private String eUserNameCn;
private int cUserId;
private String scD
private String userD
public int getUserId() {
return userId;
public void setUserId( int userId) {
this. userId = userId;
public int getCompId() {
return compId;
public void setCompId( int compId) {
this. compId = compId;
public String getEuserName() {
return euserN
public void setEuserName(String euserName) {
this. euserName = euserN
public String getEuserPhone() {
return euserP
public void setEuserPhone(String euserPhone) {
this. euserPhone = euserP
public int getEuserStatus() {
return euserS
public void setEuserStatus( int euserStatus) {
this. euserStatus = euserS
public String geteAddTime() {
return eAddT
public void seteAddTime(String eAddTime) {
this. eAddTime = eAddT
public String geteLeaveTime() {
return eLeaveT
public void seteLeaveTime(String eLeaveTime) {
this. eLeaveTime = eLeaveT
public String geteUserNameCn() {
return eUserNameCn;
public void seteUserNameCn(String eUserNameCn) {
this. eUserNameCn = eUserNameCn;
public int getcUserId() {
return cUserId;
public void setcUserId( int cUserId) {
this. cUserId = cUserId;
public String getScDown() {
return scD
public void setScDown(String scDown) {
this. scDown = scD
public String getUserDesc() {
return userD
public void setUserDesc(String userDesc) {
this. userDesc = userD
编写User.xml文件,该文件里面配置User类里面的属性和表中的那些字段进行对应,以及在UserMapper中定义的查询的方法,在User.xml中写上对应的查询语句,我这里是查的t_expand_user&表
&?xml version=&1.0& encoding= &UTF-8& ?&
&!DOCTYPE mapper
PUBLIC &-//mybatis.org//DTD Mapper 3.0//EN&
&http://mybatis.org/dtd/mybatis-3-mapper.dtd& &
&mapper namespace= &com.baimi.routerweb.mapper.UserMapper& &
&resultMap type =&User& id=&usermap&&
&result property =&userId& column=&euser_id& /&
&result property =&compId& column=&comp_id& /&
&result property =&euserName& column=&euser_name& /&
&result property =&euserPhone& column=&euser_phone& /&
&result property =&euserStatus& column=&euser_status& /&
&result property =&eAddTime& column=&e_add_time& /&
&result property =&eLeaveTime& column=&e_leave_time& /&
&result property =&eUserNameCn& column=&euser_name_cn& /&
&result property =&cUserId& column=&user_id& /&
&result property =&scDown& column=&sc_own& /&
&result property =&userDesc& column=&euser_desc& /&
&/resultMap &
&!-- 查询一条记录 --&
&select id =&getUser& parameterType=&java.lang.String& resultMap= &usermap&&
select * from t_expand_user where euser_phone=#{euserPhone}
&/select &
将User类的路径以及User.xml文件的路径在mybatis-config.xml文件中配置
&?xml version=&1.0& encoding= &UTF-8& ?&
&!DOCTYPE configuration
PUBLIC &-//mybatis.org//DTD Config 3.0//EN&
&http://mybatis.org/dtd/mybatis-3-config.dtd& &
&configuration&
&!-- 别名 --&
&typeAliases &
&typeAlias type =&com.baimi.routerweb.entity.User& alias= &User& /&
&/typeAliases &
&mappers &
&mapper resource =&com/baimi/routerweb/mapper/User.xml& /&
&/mappers &
&/configuration&
11. 写一个UserService接口(接口里面的方法和UserMapper接口里面的方法一致,返回值和参数可不同,方法名最好一致),并写UserServiceImpl来实现UserService接口
public interface UserService {
public User getUser(String euserPhone);
UserServiceImpl里面要做的就是调用UserMapper中的方法
import javax.annotation.R
import org.springframework.stereotype.S
import com.baimi.routerweb.datasource.DataSourceContextH
import com.baimi.routerweb.datasource.DataSourceT
import com.baimi.routerweb.entity.U
import com.baimi.routerweb.mapper.UserM
import com.baimi.routerweb.service.UserS
public class UserServiceImpl implements UserService {
@Resource(name = &userMapper&)
private UserMapper userM
public User getUser(String euserPhone) {
DataSourceContextHolder. setDbType(DataSourceType.SOURCE_MOP);
return userMapper.getUser(euserPhone);
12.写Controller类,并在其中写相对应的方法,给外部调用,这里主要就是两行代码:注意每次要和数据库打交道之前,切换到相对应的数据库,我的DataSourceType.&SOURCE_MOP=&ds_mop&;&这里的名字一定要和beans.xml里面配置的数据源的名称一样
//切换数据库
DataSourceContextHolder. setDbType(DataSourceType. SOURCE_MOP);
//从数据库中得到该用户的数据
User user= userService.getUser(userId);
整个Controller类的代码
import javax.annotation.R
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import net.sf.json.JSONO
import org.springframework.stereotype.C
import org.springframework.web.bind.annotation.RequestM
import com.mon.C
import com.mon.ErrorH
import com.baimi.routerweb.datasource.DataSourceContextH
import com.baimi.routerweb.datasource.DataSourceT
import com.baimi.routerweb.entity.U
import com.baimi.routerweb.service.UserS
import com.baimi.routerweb.util.HttpU
@Controller
public class MainController {
@Resource(name = &userServiceImpl&)
private UserService userS
@RequestMapping(&/login.do&)
public String login(HttpServletRequest request, HttpServletResponse response) {
// 获取客户端传过来的code的值
String code = request.getParameter( &code&);
if (code == null || &&.equals(code)) {
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, &invalid token&);
// 从微信得到token的值
JSONObject objToken = HttpUtil.httpRequest(Constant.URL_WEIXIN_TOKEN, &GET&, null);
if (objToken == null || &&.equals(objToken)) {
return ErrorHandle.getError(ErrorHandle.SERVICE_UNRESPONSE, &service unresponse&);
if (!objToken.has( &access_token&)) {
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, &invalid token&);
//根据token和code得到UserId
JSONObject objUser = HttpUtil.httpRequest(Constant.URL_GET_USERID,
&POST&, &access_token=& + objToken.getString(&access_token& )+ &&code=& + code + &&agentid=1&);
if(objUser== null|| &&.equals(objUser)){
return ErrorHandle.getError(ErrorHandle.SERVICE_UNRESPONSE, &service unresponse&);
if(!objUser.has( &UserId&)){
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, &invalid token&);
String userId=objUser.getString( &UserId&);
//切换数据库
DataSourceContextHolder. setDbType(DataSourceType.SOURCE_MOP);
//从数据库中得到该用户的数据
User user= userService.getUser(userId);
if(user!= null){
JSONObject rtObj = new JSONObject();
rtObj.put( &userId&, String.valueOf(user.getUserId()));
return rtObj.toString();
return ErrorHandle.getError(ErrorHandle.INVALID_USER,&invalid user&);
访问路径:locahost:8080/RouterWeb/login.do
demo下载地址:http://download.csdn.net/detail/q57757
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:242178次
积分:3293
积分:3293
排名:第10303名
原创:42篇
转载:303篇
评论:13条
(2)(1)(2)(4)(3)(4)(2)(10)(10)(26)(12)(6)(50)(24)(18)(3)(9)(15)(18)(23)(7)(2)(5)(20)(40)(5)(2)(1)(1)(3)(1)(15)(1)Spring下mybatis多数据源配置_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Spring下mybatis多数据源配置
&&Spring + mybatis(ibatis3)时如何使用多个数据源?
看完本文你会懂的
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢spring+mybatis 多数据源切换 - 开源中国社区
当前访客身份:游客 [
当前位置:
发布于 日 17时,
spring + mybatis 多数据源切换
代码片段(4)
1.&[代码]DbContextHolder &&&&
public class DbContextHolder {
//线程安全的ThreadLocal
private static final ThreadLocal&String& contextHolder = new ThreadLocal&String&();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
public static String getDbType() {
return ((String)contextHolder.get());
public static void clearDbType() {
contextHolder.remove();
2.&[代码]DynamicDataSource &&&&
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataS
public class DynamicDataSource extends AbstractRoutingDataSource {
public Object determineCurrentLookupKey() {
DbContextHolder.getDbType();
3.&[代码]spring.xml&&&&
&!-- 数据源属性配置文件 --&
&context:property-placeholder location="classpath:ibatis.properties" /&
&bean id="jksh" class="mons.dbcp.BasicDataSource"
destroy-method="close"&
&!-- Connection Info --&
&property name="driverClassName" value="${driver.jksh}" /&
&property name="url" value="${url.jksh}" /&
&property name="username" value="${username.jksh}" /&
&property name="password" value="${password.jksh}" /&
&!-- Connection Pooling Info --&
&property name="maxIdle" value="${maxIdle.jksh}" /&
&property name="maxActive" value="${maxActive.jksh}" /&
&property name="defaultAutoCommit" value="false" /&
&property name="timeBetweenEvictionRunsMillis"
value="${timeBetweenEvictionRunsMillis.jksh}" /&
&property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis.jksh}" /&
&bean id="jclt" class="mons.dbcp.BasicDataSource"
destroy-method="close"&
&!-- Connection Info --&
&property name="driverClassName" value="${driver.jclt}" /&
&property name="url" value="${url.jclt}" /&
&property name="username" value="${username.jclt}" /&
&property name="password" value="${password.jclt}" /&
&!-- Connection Pooling Info --&
&property name="maxIdle" value="${maxIdle.jclt}" /&
&property name="maxActive" value="${maxActive.jclt}" /&
&property name="defaultAutoCommit" value="false" /&
&property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis.jclt}" /&
&property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis.jclt}" /&
&bean id="dataSource" class="com.mons.DynamicDataSource"&
&property name="targetDataSources"&
&map key-type="java.lang.String"&
&entry key="jksh" value-ref="jksh" /&
&entry key="jclt" value-ref="jclt" /&
&/property&
&property name="defaultTargetDataSource" ref="jksh" /&
4.&[代码]main方法&&&&
import javax.sql.DataS
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
import org.springframework.core.io.FileSystemR
import org.springframework.core.io.R
import com.mons.DbContextH
import com.jclt.service.model.U
import org.apache.ibatis.session.SqlS
import org.apache.ibatis.session.SqlSessionF
import org.mybatis.spring.SqlSessionFactoryB
public class Text {
* @param args
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("client-beans.xml");
DbContextHolder.setDbType("jclt");
String res="src/main/resources/ibatis-config.xml";
DataSource datasource=(DataSource) appContext.getBean("dataSource");
SqlSessionFactoryBean bean=new SqlSessionFactoryBean();
bean.setDataSource(datasource);
Resource resource=new FileSystemResource(res);
bean.setConfigLocation(resource);
SqlSessionFactory sessionfactory = bean.getObject();
SqlSession session=sessionfactory.openSession();
User user=session.selectOne("com.jclt.service.Dao.readJKSH.findOne");
System.out.println(user.getName());
} catch (Exception e) {
e.printStackTrace();
DbContextHolder.setDbType("jksh");
String res1="src/main/resources/ibatis-config.xml";
DataSource datasource1=(DataSource) appContext.getBean("dataSource");
SqlSessionFactoryBean bean1=new SqlSessionFactoryBean();
bean1.setDataSource(datasource1);
Resource resource1=new FileSystemResource(res1);
bean1.setConfigLocation(resource1);
SqlSessionFactory sessionfactory = bean.getObject();
SqlSession session=sessionfactory.openSession();
User user=session.selectOne("com.jclt.service.Dao.readJKSH.findOne");
System.out.println(user.getName());
} catch (Exception e) {
e.printStackTrace();
开源中国-程序员在线工具:
相关的代码(405)
119回/55959阅
317回/51740阅
35回/39484阅
6回/39469阅
35回/34785阅
38回/30314阅
9回/27931阅
39回/26871阅
9回/24283阅
67回/20221阅
请问这个配置
2楼:lazy_yc 发表于
引用来自“loowj”的评论请问这个配置
吗?这个 dataSource 匹配 下面这段配置ID 因该可以把?我没试验过
3楼:lazy_yc 发表于
&bean id=&HibernateSqlSessionFactory&
&&class=&org.springframework.orm.hibernate3.LocalSessionFactoryBean&&
&&&property name=&dataSource& ref=&dataSource& /&
&dataSource 匹配&&bean id=&dataSource& class=&com.mons.DynamicDataSource&& 这段配置
4楼:loowj 发表于
如果我在一个方法中同时操作两个数据源,进行保存,事务能保证吗?
5楼:linapex 发表于
引用来自“loowj”的评论如果我在一个方法中同时操作两个数据源,进行保存,事务能保证吗?肯定不行了.需要手工控制,开启两个数据源的事务,出异常后都回滚。这一点就是,多数据源事务控制。
6楼:xhong 发表于
这种方法效率不高吧,破坏了spring的单例模式,每次都去&
SqlSessionFactoryBean bean=new&SqlSessionFactoryBean();
还不如直接配置两个 factory bean来处理
7楼:Gmupload 发表于
& 请问下,如果是并发情况下,A用户在把数据源切换到1,B用户在做查询,需要使用的是2数据源,此时会不会出现B用户查不到数据的情况呢?
8楼:小骏骏 发表于
事务管理是比较大的问题。
9楼:夜丶魂 发表于
并发才是恐怖的, mybatis是单例模式, 切换数据源时, 如果并发操作另外一个数据源的时候, 就会发现坑了
开源从代码分享开始
lazy_yc的其它代码

我要回帖

更多关于 springmvcmybatis项目 的文章

 

随机推荐