zoukankan      html  css  js  c++  java
  • 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为

     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:property-placeholder file-encoding="UTF-8" ignore-resource-not-found="true"
    10                                   location="classpath*:context/database.properties"/>
    11     <context:component-scan base-package="com.xy">
    12         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    13     </context:component-scan>
    14     <tx:annotation-driven/>
    15 
    16     <bean id="qadataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    17           destroy-method="close">
    18         <property name="jdbcUrl" value="${qa.db.url}"></property>
    19         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    20         <property name="user" value="${qa.db.user}"></property>
    21         <property name="password" value="${qa.db.password}"></property>
    22         <property name="maxPoolSize" value="20"></property>
    23         <property name="minPoolSize" value="20"></property>
    24         <property name="initialPoolSize" value="20"></property>
    25         <property name="maxIdleTime" value="200"></property>
    26         <!--<property name="numHelperThreads" value="50"></property>-->
    27     </bean>
    28 
    29     <!--<bean id="qadataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">-->
    30         <!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
    31         <!--<property name="url" value="${qa.db.url}"/>-->
    32         <!--<property name="username" value="${qa.db.user}"/>-->
    33         <!--<property name="password" value="${qa.db.password}"/>-->
    34     <!--</bean>-->
    35 
    36     <!--<bean id="devdataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">-->
    37         <!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
    38         <!--<property name="url" value="${dev.db.url}"/>-->
    39         <!--<property name="username" value="${dev.db.user}"/>-->
    40         <!--<property name="password" value="${dev.db.password}"/>-->
    41     <!--</bean>-->
    42 
    43     <bean id="devdataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    44           destroy-method="close">
    45         <property name="jdbcUrl" value="${dev.db.url}"></property>
    46         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    47         <property name="user" value="${dev.db.user}"></property>
    48         <property name="password" value="${dev.db.password}"></property>
    49         <property name="maxPoolSize" value="20"></property>
    50         <property name="minPoolSize" value="20"></property>
    51         <property name="initialPoolSize" value="20"></property>
    52         <property name="maxIdleTime" value="200"></property>
    53         <!--<property name="numHelperThreads" value="50"></property>-->
    54     </bean>
    55 
    56 
    57     <bean id="qaSessionFactory"
    58                  class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    59         <property name="packagesToScan" value="com.xy.model"/>
    60         <property name="dataSource" ref="qadataSource"/>
    61         <property name="hibernateProperties">
    62             <props>
    63                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
    64                 <prop key="hibernate.show_sql">false</prop>
    65                 <prop key="hibernate.autoReconnect">true</prop>
    66                 <prop key="hibernate.connection.release_mode">after_transaction</prop>
    67             </props>
    68         </property>
    69     </bean>
    70 
    71     <bean id="devSessionFactory"
    72           class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    73         <property name="packagesToScan" value="com.xy.model"/>
    74         <property name="dataSource" ref="devdataSource"/>
    75         <property name="hibernateProperties">
    76             <props>
    77                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
    78                 <prop key="hibernate.show_sql">false</prop>
    79                 <prop key="hibernate.autoReconnect">true</prop>
    80                 <prop key="hibernate.connection.release_mode">after_transaction</prop>
    81             </props>
    82         </property>
    83     </bean>
    84 
    85     <bean id="qaManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    86         <property name="sessionFactory" ref="qaSessionFactory" />
    87     </bean>
    88 
    89     <bean id="devManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    90         <property name="sessionFactory" ref="devSessionFactory" />
    91     </bean>
    92 
    93 </beans>
    bean配置

    其中qadataSource和devdataSource是对应两个数据库的数据源,qaSessionFactory和devSessionFactory是hibernate的sessionfactory。qaManager与devManage分别管理qadataSource和devdataSource的事务,互不干涉。注意事务管理器必须是hibernate4的类型。

    Model类如下:package com.xy.model

     1 package com.xy.model;
     2 
     3 
     4 import javax.persistence.*;
     5 
     6 /**
     7  * Created by helloworld on 2015/1/30.
     8  */
     9 @Entity
    10 @Table(name = "nameDev")
    11 public class NameDev {
    12     @Id
    13     @GeneratedValue(strategy = GenerationType.AUTO)
    14     private long id;
    15     private String nameDev;
    16 
    17     public long getId() {
    18         return id;
    19     }
    20 
    21     public void setId(long id) {
    22         this.id = id;
    23     }
    24 
    25     public String getNameDev() {
    26         return nameDev;
    27     }
    28 
    29     public void setNameDev(String nameDev) {
    30         this.nameDev = nameDev;
    31     }
    32 }
    NameDev
     1 package com.xy.model;
     2 
     3 
     4 import javax.persistence.*;
     5 
     6 /**
     7  * Created by helloworld on 2015/1/30.
     8  */
     9 @Entity
    10 @Table(name = "nameQa")
    11 public class NameQa {
    12     @Id
    13     @GeneratedValue(strategy = GenerationType.AUTO)
    14     private long id;
    15     private String nameQa;
    16 
    17     public long getId() {
    18         return id;
    19     }
    20 
    21     public void setId(long id) {
    22         this.id = id;
    23     }
    24 
    25     public String getNameQa() {
    26         return nameQa;
    27     }
    28 
    29     public void setNameQa(String nameQa) {
    30         this.nameQa = nameQa;
    31     }
    32 }
    NameQa

    处理事务的service

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

    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 /**
    13  * Created by helloworld on 2014/11/22.
    14  */
    15 @Controller
    16 public class hibernateController {
    17     @Autowired
    18     NameService nameService;
    19 
    20 
    21     @RequestMapping(value = "/addName", method = RequestMethod.POST)
    22     ModelMap addName(@RequestParam("hasQaException") boolean hasQaException,
    23                      @RequestParam("hasDevException") boolean hasDevException){
    24         try {
    25             nameService.addQa(hasQaException);
    26         } catch (Exception e) {
    27             e.printStackTrace();
    28         }
    29 
    30         try {
    31             nameService.addDev(hasDevException);
    32         } catch (Exception e) {
    33             e.printStackTrace();
    34         }
    35         return new ModelMap("true");
    36     }
    37 
    38 
    39 }
    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添加成功
    源码下载:https://files.cnblogs.com/files/rain-in-sun/springmvc-hibernate-multidatasource.rar
  • 相关阅读:
    python中xlrd模块
    2021, 8, 26模拟赛
    2021, 8,24 模拟赛
    每天挂 0 的小技巧
    2021,8,23 模拟赛
    异常处理
    64位 windows10,MYSQL8.0.13重置密码(忘记密码或者无法登录)
    Android仓库
    学习笔记索引
    「学习笔记」各类容斥反演总结
  • 原文地址:https://www.cnblogs.com/rain-in-sun/p/4314534.html
Copyright © 2011-2022 走看看