spring+hibernate管理多个数据源(非分布式事务)
本文通过一个demo,介绍如何使用spring+hibernate管理多个数据源,注意,本文的事务管理并非之前博文介绍的分布式事务。
这个demo将使用两个事务管理器分别管理两个数据源。对于每一个独立的事务,只涉及一个数据源。
demo功能:实现一个能依靠两个独立的事务管理器互不干涉的管理自己的数据源的web demo。
demo将实现:
1.独立地控制两个不同的数据源的事务管理器。
测试方式:restful web api
使用工具:
spring 4.1.1.RELEASE
hibernate 4.2.4.Final
tomcat 7
在mysql中建立两个schema,分别为dev和qa。并在里面分别建立一张名字表。
schema:dev
table:namaDev
id | nameDev
scheme:qa
table:nameQa
id | nameQa
对应的sql为
CREATE SCHEMA `qa` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
CREATE SCHEMA `dev` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; CREATE TABLE `dev`.`nameDev` (
`id` BIGINT NOT NULL AUTO_INCREMENT ,
`nameDev` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `id_UNIQUE` (`id` ASC) ); CREATE TABLE `qa`.`nameQa` (
`id` BIGINT NOT NULL AUTO_INCREMENT ,
`nameQa` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `id_UNIQUE` (`id` ASC) );
create sql
代码分析:
本项目使用spring框架,因此首先配置相关bean
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:cache="http://www.springframework.org/schema/cache" xmlns:task="http://www.springframework.org/schema/task"
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
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">
<context:property-placeholder file-encoding="UTF-8" ignore-resource-not-found="true"
location="classpath*:context/database.properties"/>
<context:component-scan base-package="com.xy">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<tx:annotation-driven/> <bean id="qadataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="jdbcUrl" value="${qa.db.url}"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="user" value="${qa.db.user}"></property>
<property name="password" value="${qa.db.password}"></property>
<property name="maxPoolSize" value="20"></property>
<property name="minPoolSize" value="20"></property>
<property name="initialPoolSize" value="20"></property>
<property name="maxIdleTime" value="200"></property>
<!--<property name="numHelperThreads" value="50"></property>-->
</bean> <!--<bean id="qadataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">-->
<!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
<!--<property name="url" value="${qa.db.url}"/>-->
<!--<property name="username" value="${qa.db.user}"/>-->
<!--<property name="password" value="${qa.db.password}"/>-->
<!--</bean>--> <!--<bean id="devdataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">-->
<!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
<!--<property name="url" value="${dev.db.url}"/>-->
<!--<property name="username" value="${dev.db.user}"/>-->
<!--<property name="password" value="${dev.db.password}"/>-->
<!--</bean>--> <bean id="devdataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="jdbcUrl" value="${dev.db.url}"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="user" value="${dev.db.user}"></property>
<property name="password" value="${dev.db.password}"></property>
<property name="maxPoolSize" value="20"></property>
<property name="minPoolSize" value="20"></property>
<property name="initialPoolSize" value="20"></property>
<property name="maxIdleTime" value="200"></property>
<!--<property name="numHelperThreads" value="50"></property>-->
</bean> <bean id="qaSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="com.xy.model"/>
<property name="dataSource" ref="qadataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
</props>
</property>
</bean> <bean id="devSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="com.xy.model"/>
<property name="dataSource" ref="devdataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.connection.release_mode">after_transaction</prop>
</props>
</property>
</bean> <bean id="qaManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="qaSessionFactory" />
</bean> <bean id="devManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="devSessionFactory" />
</bean> </beans>
bean配置
其中qadataSource和devdataSource是对应两个数据库的数据源,qaSessionFactory和devSessionFactory是hibernate的sessionfactory。qaManager与devManage分别管理qadataSource和devdataSource的事务,互不干涉。注意事务管理器必须是hibernate4的类型。
Model类如下:package com.xy.model
package com.xy.model; import javax.persistence.*; /**
* Created by helloworld on 2015/1/30.
*/
@Entity
@Table(name = "nameDev")
public class NameDev {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
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
package com.xy.model; import javax.persistence.*; /**
* Created by helloworld on 2015/1/30.
*/
@Entity
@Table(name = "nameQa")
public class NameQa {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String nameQa; public long getId() {
return id;
} public void setId(long id) {
this.id = id;
} public String getNameQa() {
return nameQa;
} public void setNameQa(String nameQa) {
this.nameQa = nameQa;
}
}
NameQa
处理事务的service
package com.xy.service; import com.xy.model.NameDev;
import com.xy.model.NameQa;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; /**
* Created by helloworld on 2015/1/30.
*/
@Service
public class NameService {
@Autowired
private SessionFactory qaSessionFactory;
@Autowired
private SessionFactory devSessionFactory; @Transactional(value = "qaManager",rollbackFor = Exception.class)
public void addQa(boolean hasQaException) throws Exception {
NameQa nameQa = new NameQa();
nameQa.setNameQa("hello");
qaSessionFactory.getCurrentSession().save(nameQa); if(hasQaException){
throw new Exception();
}
} @Transactional(value = "devManager", rollbackFor = Exception.class)
public void addDev(boolean hasDevQaException) throws Exception {
NameDev nameDev = new NameDev();
nameDev.setNameDev("hello");
devSessionFactory.getCurrentSession().save(nameDev); if(hasDevQaException){
throw new Exception();
}
} }
service
controller代码
package com.xy.controller; import com.xy.service.NameService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; /**
* Created by helloworld on 2014/11/22.
*/
@Controller
public class hibernateController {
@Autowired
NameService nameService; @RequestMapping(value = "/addName", method = RequestMethod.POST)
ModelMap addName(@RequestParam("hasQaException") boolean hasQaException,
@RequestParam("hasDevException") boolean hasDevException){
try {
nameService.addQa(hasQaException);
} catch (Exception e) {
e.printStackTrace();
} try {
nameService.addDev(hasDevException);
} catch (Exception e) {
e.printStackTrace();
}
return new ModelMap("true");
} }
controller
将项目打成war包,命名为test.war部署在tomcat上。
测试:
1.POST http://localhost:8080/test/addName.json
request parameters:
withDevException=false
witQaException=false
返回:true 两个数据都添加成功
2.POST http://localhost:8080/test/addName.json
request parameters:
withDevException=false
witQaException=true
返回:true 只有dev添加成功
源码下载:http://files.cnblogs.com/files/rain-in-sun/springmvc-hibernate-multidatasource.rar
spring+hibernate管理多个数据源(非分布式事务)的更多相关文章
- spring+mybatis管理多个数据源(非分布式事务)
本文通过一个demo,介绍如何使用spring+mybatis管理多个数据源,注意,本文的事务管理并非之前博文介绍的分布式事务. 这个demo将使用两个事务管理器分别管理两个数据源.对于每一个独立的事 ...
- spring+hibernate 配置多个数据源过程 以及 spring中数据源的配置方式
spring+hibernate 配置多个数据源过程 以及 spring中数据源的配置方式[部分内容转载] 2018年03月27日 18:58:41 守望dfdfdf 阅读数:62更多 个人分类: 工 ...
- springboot整合多数据源解决分布式事务
一.前言 springboot整合多数据源解决分布式事务. 1.多数据源采用分包策略 2.全局分布式事务管理:jta-atomikos. ...
- 【Rocket MQ】RocketMQ4.2.0 和 spring boot的结合使用,实现分布式事务
RocketMQ4.2.0 和 spring boot的结合使用,实现分布式事务 参考地址:https://www.jianshu.com/p/f57de40621a0
- atomikos实现多数据源支持分布式事务管理(spring、tomcat、JTA)
原文链接:http://iteye.blog.163.com/blog/static/1863080962012102945116222/ Atomikos TransactionsEssenti ...
- Spring3.0+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
一.概念 分布式事务分布式事务是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上.简言之,同时操作多个数据库保持事务的统一,达到跨库事务的效果. JTA ...
- SpringCloud微服务实战——搭建企业级开发框架(二十七):集成多数据源+Seata分布式事务+读写分离+分库分表
读写分离:为了确保数据库产品的稳定性,很多数据库拥有双机热备功能.也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器:第二台数据库服务器,主要进行读的操作. 目前有多种方式实现读写分离,一种 ...
- Spring Trasnaction管理(1)- 线程间事务隔离
问题导读 Spring中事务是如何实现的 Spring中各个线程间是如何进行连接.事务隔离的 Spring事务配置 Spring的事务管理应该是日常开发中总会碰到的,但是Spring具体是怎么实现线程 ...
- 使用Atomikos Transactions Essentials实现多数据源JTA分布式事务--转载
原文:http://www.ite/topic/122700 9.17 update:使用NonXADataSourceBean. Mysql在5.0版本和Connecter/J5.0版本后提供了XA ...
随机推荐
- UVa 1252 Twenty Questions (状压DP+记忆化搜索)
题意:有n件物品,每件物品有m个特征,可以对特征进行询问,询问的结果是得知某个物体是否含有该特征,要把所有的物品区分出来(n个物品的特征都互不相同), 最小需要多少次询问? 析:我们假设心中想的那个物 ...
- UVaLive 7363 A Rational Sequence (二叉树)
题意:给定一个二叉树,并对每一个进行编号和规定,现在给你一个值,问你是第几个. 析:这个题,我想了好久才想出来,这个真是数据结构练的太差了,不够扎实,这个题,应该从下向上推,如果分子大于分母,那么这个 ...
- CodeForces 589I Lottery (暴力,水题)
题意:给定 n 和 k,然后是 n 个数,表示1-k的一个值,问你修改最少的数,使得所有的1-k的数目都等于n/k. 析:水题,只要用每个数减去n/k,然后取模,加起来除以2,就ok了. 代码如下: ...
- Android中回调接口的使用
MainActivity如下: package cn.testcallback; import android.os.Bundle; import android.app.Activity; /** ...
- VHDL的testbench的编写(转)
大多数硬件设计人员对verilog的testbench比较熟悉,那是因为verilog被设计出来的目的就是为了用于测试使用,也正是因为这样verilog的语法规则才被设计得更像C语言,而verilog ...
- Unity3D之飞机游戏追踪导弹制作
最近开发完成一款打飞机的游戏,记录一下制作追踪导弹的方法,最开始在网上找到的资料制作出来的追踪导弹都不够真实,主要的问题是没有对导弹进行一个阀值处理,导弹每帧都始终会面向目标,而不是按照一定的角度进行 ...
- opencv 手势识别
我使用OpenCV2.4.4的windows版本+Qt4.8.3+VS2010的编译器做了一个手势识别的小程序. 本程序主要使到了Opencv的特征训练库和最基本的图像处理的知识,包括肤色检测等等. ...
- Windows 7 bug: nonexistent Java Runtime Enviroment
When I tried installing atunes and TED, I got the message “The registry refers to a nonexistent Java ...
- ADO.NET 快速入门(五):从 DataSet 更新数据库
该主题说明了如何使用 DataSet 在数据库中更新数据.你依然可以直接使用 SqlCommand 在数据库中插入.更新.和删除数据,记住这一点也很重要.理解“从数据库填充DataSet”涵盖的概念有 ...
- strutx.xml中配置文件的讲解
Struts2框架的核心就是struts.xml文件了,该文件主要负责管理Struts的2的业务控制组件的核心内容.为了避免struts.xml的文件国 语庞大和臃肿,我们可以通过把一个struts. ...