spring+mybatis管理多个数据源(非分布式事务)

本文通过一个demo,介绍如何使用spring+mybatis管理多个数据源,注意,本文的事务管理并非之前博文介绍的分布式事务。

这个demo将使用两个事务管理器分别管理两个数据源。对于每一个独立的事务,只涉及一个数据源。

demo功能:实现一个能依靠两个独立的事务管理器互不干涉的管理自己的数据源的web demo。

demo将实现:

1.独立地控制两个不同的数据源的事务管理器。

测试方式:restful web api

使用工具:

spring 4.1.1.RELEASE

mybatis 3.2.7

tomcat 7

在mysql中建立两个schema,分别为dev和qa。并在里面分别建立一张名字表。

schema:dev

table:namaDev

id | nameDev

scheme:qa

table:nameQa

id  |  nameQa

对应的sql为

 1 CREATE SCHEMA `qa` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
 2 CREATE SCHEMA `dev` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
 3
 4  CREATE  TABLE `dev`.`nameDev` (
 5   `id` BIGINT NOT NULL AUTO_INCREMENT ,
 6   `nameDev` VARCHAR(45) NULL ,
 7   PRIMARY KEY (`id`) ,
 8   UNIQUE INDEX `id_UNIQUE` (`id` ASC) );
 9
10   CREATE  TABLE `qa`.`nameQa` (
11   `id` BIGINT NOT NULL AUTO_INCREMENT ,
12   `nameQa` VARCHAR(45) NULL ,
13   PRIMARY KEY (`id`) ,
14   UNIQUE INDEX `id_UNIQUE` (`id` ASC) );

create sql

代码分析:

本项目使用spring框架,因此首先配置相关bean

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
 4        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
 5        xmlns:rabbit="http://www.springframework.org/schema/rabbit"
 6        xmlns:cache="http://www.springframework.org/schema/cache" xmlns:task="http://www.springframework.org/schema/task"
 7        xsi:schemaLocation="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.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
 8        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
 9     <context:component-scan base-package="com.xy">
10         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
11     </context:component-scan>
12     <context:property-placeholder location="classpath:context/database.properties"/>
13     <tx:annotation-driven/>
14
15     <bean id="qadataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
16                  destroy-method="close">
17         <property name="jdbcUrl" value="${qa.db.url}"></property>
18         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
19         <property name="user" value="${qa.db.user}"></property>
20         <property name="password" value="${qa.db.password}"></property>
21         <property name="maxPoolSize" value="20"></property>
22         <property name="minPoolSize" value="20"></property>
23         <property name="initialPoolSize" value="20"></property>
24         <property name="maxIdleTime" value="200"></property>
25         <!--<property name="numHelperThreads" value="50"></property>-->
26     </bean>
27
28     <bean id="devdataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
29           destroy-method="close">
30         <property name="jdbcUrl" value="${dev.db.url}"></property>
31         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
32         <property name="user" value="${dev.db.user}"></property>
33         <property name="password" value="${dev.db.password}"></property>
34         <property name="maxPoolSize" value="20"></property>
35         <property name="minPoolSize" value="20"></property>
36         <property name="initialPoolSize" value="20"></property>
37         <property name="maxIdleTime" value="200"></property>
38         <!--<property name="numHelperThreads" value="50"></property>-->
39     </bean>
40
41
42
43
44
45     <bean id="qasqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
46         <property name="dataSource" ref="qadataSource" />
47         <!--<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />-->
48     </bean>
49
50     <bean id="devsqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
51         <property name="dataSource" ref="devdataSource" />
52         <!--<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />-->
53     </bean>
54
55     <bean id="qaManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
56         <property name="dataSource" ref="qadataSource" />
57     </bean>
58
59     <bean id="devManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
60         <property name="dataSource" ref="devdataSource" />
61     </bean>
62
63
64
65     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
66         <property name="basePackage" value="com.xy.dao"/>
67         <property name="sqlSessionFactoryBeanName" value="qasqlSessionFactory" />
68     </bean>
69
70     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
71         <property name="basePackage" value="com.xy.daodev"/>
72         <property name="sqlSessionFactoryBeanName" value="devsqlSessionFactory" />
73     </bean>
74
75
76 </beans>

其中qadataSource和devdataSource是对应两个数据库的数据源,qasqlSessionFactory和devsqlSessionFactory是mybatis的sessionfactory,两个MapperScannerConfigurer自动将不同数据源的sql语句文件与interface自动装配起来。qaManager与devManage分别管理qadataSource和devdataSource的事务,互不干涉。

Model类如下:package com.xy.model

package com.xy.model;

/**
 * Created by helloworld on 2015/1/30.
 */
public class NameDev {
    private long id;
    private String nameDev;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getNameDev() {
        return nameDev;
    }

    public void setNameDev(String nameDev) {
        this.nameDev = nameDev;
    }
}

NameDev

 1 package com.xy.model;
 2
 3 /**
 4  * Created by helloworld on 2015/1/30.
 5  */
 6 public class NameQa {
 7     private long id;
 8     private String nameQa;
 9
10     public long getId() {
11         return id;
12     }
13
14     public void setId(long id) {
15         this.id = id;
16     }
17
18     public String getNameQa() {
19         return nameQa;
20     }
21
22     public void setNameQa(String nameQa) {
23         this.nameQa = nameQa;
24     }
25 }

NameQa

qa数据源的mybatis mapper接口 package com.xy.dao

 1 package com.xy.dao;
 2
 3 import com.xy.model.NameQa;
 4
 5 /**
 6  * Created by helloworld on 2015/1/30.
 7  */
 8 public interface NameQaMapper {
 9     int insert(NameQa nameQa);
10 }

NameQaMapper

dev数据源的mybatis mapper接口 package com.xy.devdao

 1 package com.xy.daodev;
 2
 3 import com.xy.model.NameDev;
 4
 5 /**
 6  * Created by helloworld on 2015/1/30.
 7  */
 8 public interface NameDevMapper {
 9     int insert(NameDev nameDev);
10 }

NameDevMapper

处理事务的service

 1 package com.xy.service;
 2
 3 import com.xy.dao.NameQaMapper;
 4 import com.xy.daodev.NameDevMapper;
 5 import com.xy.model.NameDev;
 6 import com.xy.model.NameQa;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.stereotype.Service;
 9 import org.springframework.transaction.annotation.Transactional;
10
11 /**
12  * Created by helloworld on 2015/1/30.
13  */
14 @Service
15 public class NameService {
16     @Autowired
17     NameQaMapper nameQaMapper;
18     @Autowired
19     NameDevMapper nameDevMapper;
20
21     @Transactional(value = "qaManager", rollbackFor = Exception.class)
22     public void addQa(boolean withQaException) throws Exception {
23         NameQa nameQa = new NameQa();
24         nameQa.setNameQa("hello");
25         nameQaMapper.insert(nameQa);
26
27         if(withQaException){
28             throw new Exception();
29         }
30     }
31
32     @Transactional(value = "devManager", rollbackFor = Exception.class)
33     public void addDev(boolean withDevException) throws Exception {
34         NameDev nameDev = new NameDev();
35         nameDev.setNameDev("hello");
36         nameDevMapper.insert(nameDev);
37
38         if(withDevException){
39             throw new Exception();
40         }
41     }
42
43 }

NameService

controller代码

 1 package com.xy.controller;
 2
 3 import com.xy.service.NameService;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.stereotype.Controller;
 6 import org.springframework.ui.ModelMap;
 7 import org.springframework.web.bind.annotation.RequestMapping;
 8 import org.springframework.web.bind.annotation.RequestMethod;
 9 import org.springframework.web.bind.annotation.RequestParam;
10
11 /**
12  * Created by helloworld on 2014/11/22.
13  */
14 @Controller
15 public class mybatisController {
16
17     @Autowired
18     NameService nameService;
19
20     @RequestMapping(value = "/addName", method = RequestMethod.POST)
21     ModelMap addName(@RequestParam("withDevException") boolean withDevException,
22                      @RequestParam("witQaException") boolean witQaException ) {
23         try {
24             nameService.addDev(withDevException);
25         } catch (Exception e) {
26             e.printStackTrace();
27         }
28
29         try {
30             nameService.addQa(witQaException);
31         } catch (Exception e) {
32             e.printStackTrace();
33         }
34         return new ModelMap("true");
35     }
36
37
38 }

controller

将项目打成war包,命名为mybatis.war部署在tomcat上。

测试:

1.POST  http://localhost:8080/mybatis/addName.json

request parameters:
withDevException=false
witQaException=false
返回:true 两个数据都添加成功

2.POST  http://localhost:8080/mybatis/addName.json

request parameters:
withDevException=false
witQaException=true
返回:true 只有dev添加成功
源码下载:http://files.cnblogs.com/files/rain-in-sun/springmvc-mybatis-multidatasource.rar
时间: 2024-10-13 12:25:13

spring+mybatis管理多个数据源(非分布式事务)的相关文章

Spring+Mybatis+SpringMVC+Atomikos多数据源共存+分布式事物处理

网上找了一大堆的例子,没一个跑通的,都是copy转发,哎,整理得好辛苦..做个笔记,方便正遇到此问题的猿们能够得到帮助....废话不多说,贴代码..... 项目结构说明: 1.dao层的admin.website包中包含的Mapper.xml文件分别操作不同的数据库 2.举例:192.168.1.1下有个mysql数据库叫 odao_admin 192.168.1.2下有个sqlserver数据库叫 odao_mobile 详情见下方的jdbc.properties文件 1:Pom.xml <p

spring+hibernate管理多个数据源(非分布式事务)

本文通过一个demo,介绍如何使用spring+hibernate管理多个数据源,注意,本文的事务管理并非之前博文介绍的分布式事务. 这个demo将使用两个事务管理器分别管理两个数据源.对于每一个独立的事务,只涉及一个数据源. demo功能:实现一个能依靠两个独立的事务管理器互不干涉的管理自己的数据源的web demo. demo将实现: 1.独立地控制两个不同的数据源的事务管理器. 测试方式:restful web api 使用工具: spring 4.1.1.RELEASE hibernat

使用Atomikos Transactions Essentials实现多数据源JTA分布式事务--转载

原文:http://www.ite/topic/122700 9.17 update:使用NonXADataSourceBean. Mysql在5.0版本和Connecter/J5.0版本后提供了XADatasource支持,如果使用了支持XADatasouce版本,可以参考2楼补充. 最近做的project中遇到要将数据库中的表分布到两台不同的服务器上的Mysql5.0中,project主要使用spring+ibatis.因此需要JTA的支持,但是tomcat不支持,所以就搜索开源的JTA实现

多数据源问题--Spring+Ibatis 访问多个数据源(非分布式事务)

有的时候,我在一个工程中需要访问两个以上的数据源,尤其是在系统集成的时候,以下是我在系统集成的时候遇到的情况,我的工程的架构是:spring2.0+ibatis2.0+struts1.2. 数据库是oracle数据库,而需要集成的系统是sql server数据库,对方没有提供接口,要求直接操作sql server库.以下是spring配置文件中配置了两个数据源,包括service事务.实际上要把applicationContext.xml中的dao部分独立到daoContext.xml文件中,为

spring+mybatis最简多数据源配置

作者:纯洁的微笑出处:http://www.ityouknow.com/ 版权所有,欢迎保留原文链接进行转载:) 说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解决方案,还有的是利用aop动态切换,感觉有点小复杂,其实我只是想找一个简单的多数据支持而已,折腾了两个小时整理出来,供大家参考. 废话不多说直接上代码吧 配置文件 pom包就不贴了比较简

Spring配置文件中的C3P0数据源配置和事务配置(采用mysql)

直接上代码 <?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:aop="http://www.springframework.org/s

spring+mybatis事务管理

spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数据库配置这方面的东西吧,今天给大家分享一下关于spring+mybatis管理事务这方面得知识吧. 先说说spring管理事务的集中方式,我所了解的有两种:第一种是编程式事务管理,第二种是声明式事务管理,而声明式事务管理中又有两种,一种是配置方式,另一种是声明式.我们在工作中一般都使用声明式事务管理

Spring Cloud同步场景分布式事务怎样做?试试Seata

一.概述 在微服务架构下,虽然我们会尽量避免分布式事务,但是只要业务复杂的情况下这是一个绕不开的问题,如何保证业务数据一致性呢?本文主要介绍同步场景下使用Seata的AT模式来解决一致性问题. Seata是 阿里巴巴 开源的 一站式分布式事务解决方案 中间件,以 高效 并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题 ? 二.Seata介绍 整体事务逻辑是基于 两阶段提交 的模型,核心概念包括以下3个角色: TM:事务的发起者.用来告诉 TC,全局事务的开始,提交,回滚.

分布式事务系列(开篇)提出疑问和研究过程

1 前言 对于我们这种初学者,可能会使用spring带给我们的@Transactional,可能了解JTA,可能会使用jotm.atomikos,又会遇到一些名词XA,支持XA的数据库驱动等等诸多问题,然后就会愈加混乱,自然形成一个疑问,庞大的事务体系的全貌到底是什么样? 2 需要解决的疑惑 下面就要具体列出一系列需要解决的问题 2.1 对于事务模型 三种事务模型是什么?各自的特点是什么?各自的缺陷是什么? 2.2 spring对于事务模型的支持 spring自己的一系列接口设计: Platfo