SpringBoot中配置多个数据源、多个数据源存在的问题-day02下

6.4 SpringBoot中配置多个数据源

  • 就是操作多个数据库所要进行的配置

第一步:准备2个数据库

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 80013
Source Host           : localhost:3306
Source Database       : test

Target Server Type    : MYSQL
Target Server Version : 80013
File Encoding         : 65001

Date: 2020-10-26 21:14:40
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'zhangsan', '1234');
INSERT INTO `user` VALUES ('2', 'lisi', '1234');
INSERT INTO `user` VALUES ('4', 'shu', '123');
INSERT INTO `user` VALUES ('5', 'shu1', '123');

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 80013
Source Host           : localhost:3306
Source Database       : test1

Target Server Type    : MYSQL
Target Server Version : 80013
File Encoding         : 65001

Date: 2020-10-26 21:14:50
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `sex` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', 'shu', '男');

在这里插入图片描述

第二步:pom中添加依赖

在这里插入图片描述

<repositories>
    <repository>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </repository>
  </repositories>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <parent>
    <!--SpringBoot的父依赖-->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
  </parent>

  <dependencies>
    <!--SpringBoot配置web依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--引入freeMarker的依赖包-->
    <!--<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>-->
    <!--JDBC-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!--数据库驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.13</version>
    </dependency>
    <!--单元测试-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!--Mybatis-->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.1.1</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.*</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.*</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

第三步:application.properties配置文件中添加两个数据源

在这里插入图片描述

spring.datasource.test.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.test.username=root
spring.datasource.test.password=root
spring.datasource.test.driverClassName=com.mysql.cj.jdbc.Driver

spring.datasource.test1.url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC
spring.datasource.test1.username=root
spring.datasource.test1.password=root
spring.datasource.test1.driverClassName=com.mysql.cj.jdbc.Driver

可能有用:
springboot1.x 版本用url、driverClassName
springboot2.x 版本用jdbc-url、driver-class-name

第四步:写2个数据源配置

  • 数据源1
    在这里插入图片描述
package com.it.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @ClassName DataSource1
 * @Author shuyy
 * @Date 2020/10/26
 **/

@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.it.test.mapper",sqlSessionFactoryRef="testSqlSessionFactory")
public class DataSource1 {
    
    

        /**
         * @return 返回test数据库的数据源
         */
        @Bean(name="testDataSource")
        @Primary//主数据源,一个应用只能配置一个(一山不容二虎),且必须配置,这里不配置报错!
        @ConfigurationProperties(prefix="spring.datasource.test")
        public DataSource dateSource(){
    
    
            return DataSourceBuilder.create()//如果失败了可以使用下面这种方法
                    /*.driverClassName("com.mysql.cj.jdbc.Driver")
                    .url("jdbc:mysql://localhost:3306/test?serverTimezone=UTC")
                    .username("root")
                    .password("root")*/
                    .build();
        }

        /**
         * @return 返回test数据库的会话工厂
         */
        @Bean(name = "testSqlSessionFactory")
        @Primary
        public SqlSessionFactory sqlSessionFactory(@Qualifier("testDataSource") DataSource ds) throws Exception{
    
    
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(ds);
            //这里使用的是注解+接口sql无需配置,如果是xml中写sql,记得配置
            //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:test/mapper/*.xml"));
            return bean.getObject();
        }

        /**
         * @return 返回test数据库的事务
         */
        @Bean(name = "testTransactionManager")
        @Primary
        public DataSourceTransactionManager transactionManager(@Qualifier("testDataSource") DataSource dataSource) {
    
    
            return new DataSourceTransactionManager(dataSource);
        }

        /**
         * @return 返回test数据库的会话模版
         */
        @Bean(name = "testSqlSessionTemplate")
        @Primary
        public SqlSessionTemplate sqlSessionTemplate(
                @Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    
    
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }

  • 数据源2
    在这里插入图片描述
package com.it.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;


@Configuration//注解到springboot容器中
@MapperScan(basePackages="com.it.test1.mapper",sqlSessionFactoryRef="test1SqlSessionFactory")
public class DataSource2 {
    
    

    /**
     * @return 返回test1数据库的数据源
     */
    @Bean(name="test1DataSource")
    @ConfigurationProperties(prefix="spring.datasource.test1")
    public DataSource dateSource(){
    
    
        return DataSourceBuilder.create()
                /*.driverClassName("com.mysql.cj.jdbc.Driver")
                .url("jdbc:mysql://localhost:3306/test1?serverTimezone=UTC")
                .username("root")
                .password("root")*/
                .build();
    }

    /**
     * @return 返回test1数据库的会话工厂
     */
    @Bean(name = "test1SqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("test1DataSource") DataSource ds) throws Exception{
    
    
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
        //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:test1/mapper/*.xml"));
        return bean.getObject();
    }

    /**
     * @return 返回test1数据库的事务
     */
    @Bean(name = "test1TransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
    
    
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * @return 返回test1数据库的会话模版
     */
    @Bean(name = "test1SqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(
            @Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

第五步:实体类编写

  • User,【对应数据库字段】为属性提供无参、有参构造、get/set、toString
    在这里插入图片描述
  • Student,为属性提供无参、有参构造、get/set、toString
    在这里插入图片描述

第六步:test的Mapper&service

  • UserMapper
    在这里插入图片描述
package com.it.test.mapper;


import com.it.test.model.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
    
    

    @Insert("insert into user(username,password) values(#{username},#{password})")
    void save(@Param("username") String username, @Param("password") String password);

    @Select("select * from user where id = #{id}")
    User findUserById(@Param("id") Integer id);
    /*void save(String username,String password);
    User findUserById(Integer id);*/
}

  • UserService
    在这里插入图片描述

  • UserServiceImpl
    在这里插入图片描述

package com.it.test.service.impl;

import com.it.test.mapper.UserMapper;
import com.it.test.model.User;
import com.it.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @ClassName UserServiceImpl
 * @Author shuyy
 * @Date 2020/10/26
 **/
@Service
@Transactional
public class UserServiceImpl implements UserService {
    
    

    @Autowired
    private UserMapper userMapper;//这里如果报错,正常不影响运行,是springBean扫描所致,它是在运行时自动创建
    /*private JdbcTemplate jdbcTemplate;*///本来这里需要配置数据源,现在在SpringBoot中配置好了无需配置

    @Override
    public void register(String username, String password) {
    
    
        /*String sql = "insert into user(username,password) values(?,?)";*/
        /*jdbcTemplate.update(sql,username,password);*/
        userMapper.save(username,password);
    }

    @Override
    public User findUserById(Integer id) {
    
    
        return userMapper.findUserById(id);
    }
}

第七步:test1的Mapper&service

  • StudentMapper
    在这里插入图片描述
package com.it.test1.mapper;

import com.it.test1.model.Student;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * @author ShuYY
 * @date 2020/10/26
 */
public interface StudentMapper {
    
    

    @Insert("insert into student(username,sex) values(#{username},#{sex})")
    void save(@Param("username") String username, @Param("sex") String sex);

    @Select("select * from student where id = #{id}")
    Student findStuById(@Param("id") Integer id);

    /*void save(String username,String sex);
    Student findStuById(Integer id);*/
}

  • StudentService
    在这里插入图片描述
  • StudentServiceImpl
    在这里插入图片描述
package com.it.test1.service.impl;/**
 * @author ShuYangyang
 * @date 2020/10/26 21:46
 */

import com.it.test1.mapper.StudentMapper;
import com.it.test1.model.Student;
import com.it.test1.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @ClassName StudentServiceImpl
 * @Author shuyy
 * @Date 2020/10/26
 **/
@Service
@Transactional
public class StudentServiceImpl implements StudentService {
    
    

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public void save(String username, String sex) {
    
    
        studentMapper.save(username,sex);
    }

    @Override
    public Student findStuById(Integer id) {
    
    
        return studentMapper.findStuById(id);
    }
}

第八步:写个Controller

  • UserController
    在这里插入图片描述
package com.it.web.controller;

import com.it.test.model.User;
import com.it.test.service.UserService;
import com.it.test1.model.Student;
import com.it.test1.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName HelloController
 * @Author shuyy
 * @Date 2020/10/25
 **/
@RestController
@RequestMapping("user")
public class UserController {
    
    

    @Autowired
    private UserService userService;

    @Autowired
    private StudentService studentService;

    @RequestMapping("register")
    @ResponseBody
    public String register(String username,String password){
    
    
        userService.register(username,password);
        studentService.save(username,"男");
        return "success";
    }

    @RequestMapping("findUser")
    @ResponseBody
    public User findUser(Integer id){
    
    
        return userService.findUserById(id);
    }

    @RequestMapping("findStu")
    @ResponseBody
    public Student findStu(Integer id){
    
    
        return studentService.findStuById(id);
    }

}

第九步:App中

在这里插入图片描述

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

/**
 * @ClassName App
 * @Author shuyy
 * @Date 2020/10/25
 **/


@EnableAutoConfiguration/*(exclude={DataSourceAutoConfiguration.class})*///写一个,这里配置了,其它Controller无需写了
@ComponentScan(basePackages = {
    
    "com.it.datasource","com.it.web.controller","com.it.test","com.it.test1"})//配置扫描包
public class App {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(App.class,args);
    }
}

效果

在这里插入图片描述

6.5 多数据源存在的问题

  1. 修改UserController
    在这里插入图片描述
  2. 修改对应的方法
    在这里插入图片描述
    在这里插入图片描述
  3. 注意这里调换一下方法的顺序!
    在这里插入图片描述
  4. 显然上面这样是不符合事务的要求的,要么全部成功要么全部失败,我们要把它当成一个事务看待处理,就要使用到springboot+jta+atomikos 分布式事务管理来解决这样的现象。(详见下一天)

猜你喜欢

转载自blog.csdn.net/qq_43414199/article/details/109298803
今日推荐