Spring Boot学习笔记(七)SpringBoot:JPA + Druid 多数据源

SpringBoot:JPA + Druid 多数据源

参考出处, 根据Spring版本不同做出了相应的调整
上一篇:Spring Data JPA:分类查询、自定义查询、联表(多表查询)

  • 创建两个数据库test和books,test数据库包含t_user表,books包含book表:

    t_user表建立:

    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for t_user
    -- ----------------------------
    DROP TABLE IF EXISTS `t_user`;
    CREATE TABLE `t_user`  (
      `t_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
      `t_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称',
      `t_age` int(10) NULL DEFAULT NULL COMMENT '年龄',
      `t_address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '家庭住址',
      `t_pwd` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '用户登录密码',
      PRIMARY KEY (`t_id`) USING BTREE
    ) ENGINE = MyISAM AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of t_user
    -- ----------------------------
    INSERT INTO `t_user` VALUES (1, 'Ray', 6, 'zh', '123');
    INSERT INTO `t_user` VALUES (2, 'q343509740', 18, 'zh', '456');
    INSERT INTO `t_user` VALUES (3, 'Rain', 24, 'zh', '789');
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    book表建立:

    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for book
    -- ----------------------------
    DROP TABLE IF EXISTS `book`;
    CREATE TABLE `book`  (
      `b_id` int(11) NOT NULL AUTO_INCREMENT,
      `b_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`b_id`) USING BTREE
    ) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of book
    -- ----------------------------
    INSERT INTO `book` VALUES (1, 'SpringBoot入门');
    INSERT INTO `book` VALUES (2, 'SpringData实战');
    INSERT INTO `book` VALUES (3, 'SpringData放弃');
    
    SET FOREIGN_KEY_CHECKS = 1;
    
  • 目录结构:

    Spring Boot学习笔记(七)SpringBoot:JPA + Druid 多数据源_第1张图片

  • pom.xml 导入依赖:
    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.1.6.RELEASE
             
        
        wen
        datademo
        0.0.1-SNAPSHOT
        datademo
        Demo project for Spring Boot
    
        
            1.8
        
    
        
            
            
                org.springframework.boot
                spring-boot-starter-data-jpa
            
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
            
                com.alibaba
                druid-spring-boot-starter
                1.1.9
            
    
            
            
                mysql
                mysql-connector-java
                runtime
            
    
            
            
                org.projectlombok
                lombok
                true
            
    
            
                org.springframework.boot
                spring-boot-starter
            
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
            
        
    
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                
            
        
    
    
    
    
  • application.properties文件配置
    # 数据库配置公共属性
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.username=root
    spring.datasource.password=
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    # user, book 数据库的配置
    spring.datasource.user.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone = GMT
    spring.datasource.book.url=jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone = GMT
    # Druid 常用配置
    # 配置控制统计拦截的filters,去掉后监控界面sql将无法统计,wall用于防火墙
    spring.datasource.druid.filter=stat,wall
    # 最大活跃数
    spring.datasource.druid.max-active=20
    # 初始化数量
    spring.datasource.druid.initial-size=1
    # 最小连接池数量
    spring.datasource.druid.min-idle=1
    # 最大连接等待超时时间
    spring.datasource.druid.max-wait=60000
    # 打开PSCache,并且指定每个连接PSCache的大小,mysql可以设置为false
    spring.datasource.druid.pool-prepared-statements=false
    spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
    # 配置间隔多久才进行一次检测,检测需要关闭的空间连接,单位是毫秒
    spring.datasource.druid.time-between-eviction-runs-millis=60000
    # 用来检测连接是否有效
    spring.datasource.druid.validation-query=SELECT 1
    spring.datasource.druid.test-while-idle=true
    spring.datasource.druid.test-on-borrow=false
    spring.datasource.druid.test-on-return=false
    spring.datasource.druid.async-init=true
    spring.jpa.properties.hibernate.show_sql=true
    spring.jpa.properties.hibernate.format_sql=true
    

    user, book 数据库的配置时前缀名分别为:spring.datasource.user与spring.datasource.book,这两个前缀名在配置默认数据源的时候会用到

  • 自定义数据源配置类DataSourceConfig.java:包名wen.multisourcedata.comm
    package wen.multidatasource.comm;
    
    import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
    import org.springframework.beans.factory.annotation.Qualifier;
    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 javax.sql.DataSource;
    
    @Configuration
    public class DataSourceConfig {
    
        //用户数据源
        @Bean(name = "userDataSource")
        @Qualifier(value = "userDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.user")
        public DataSource userDataSource() {
            return DruidDataSourceBuilder.create().build();
        }
    
        //书籍数据源
        @Bean(name = "bookDataSource")
        @Primary
        @Qualifier(value = "bookDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.book")
        public DataSource bookDataSource() {
            return DruidDataSourceBuilder.create().build();
        }
    }
    
    
    • @Bean(name = “userDataSource”) : 装配该方法返回值为userDataSource管理Bean
    • @Qualifier(value = “userDataSource”) : Spring注入时的唯一标识防止注入冲突
    • @ConfigurationProperties(prefix = “spring.datasource.user”) : 上文提到的前缀配置数据源
    • @Primary : 配置数据源为主数据源
  • BookDataSourceConfig.java:
    package wen.multidatasource.comm;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryBook",
            transactionManagerRef = "transactionManagerBook",
            basePackages = {"wen.multidatasource.dao.bookjpa"})
    public class BookDataSourceConfig {
    
        @Autowired
        private HibernateProperties hibernateProperties;
    
        @Autowired
        @Qualifier("bookDataSource")
        private DataSource bookDataSource;
    
        @Autowired
        private JpaProperties jpaProperties;
    
        @Primary
        @Bean(name = "entityManagerFactoryBook")
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryBook(EntityManagerFactoryBuilder builder) {
    
            Map properties = hibernateProperties.determineHibernateProperties(
                    jpaProperties.getProperties(), new HibernateSettings());
            return builder
                    .dataSource(bookDataSource)
                    .properties(properties)
                    .packages(new String[]{"wen.multidatasource.domain"})
                    .persistenceUnit("bookPersistenceUnit")
                    .build();
        }
    
        @Primary
        @Bean(name = "transactionManagerBook")
        public PlatformTransactionManager transactionManagerBook(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryBook(builder).getObject());
        }
    
        @Primary
        @Bean(name = "entityManagerBook")
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryBook(builder).getObject().createEntityManager();
        }
    }
    
    
  • 和 UserDataSourceConfig.java:
    package wen.multidatasource.comm;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
    import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.persistence.EntityManager;
    import javax.sql.DataSource;
    import java.util.Map;
    
    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = "entityManagerFactoryUser",
            transactionManagerRef = "transactionManagerUser",
            basePackages = {"wen.multidatasource.dao.userjpa"})
    public class UserDataSourceConfig {
    
        @Autowired
        private HibernateProperties hibernateProperties;
    
        @Autowired
        @Qualifier("userDataSource")
        private DataSource userDataSource;
    
        @Autowired
        private JpaProperties jpaProperties;
    
        @Bean(name = "entityManagerFactoryUser")
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryUser(EntityManagerFactoryBuilder builder) {
    
            Map properties = hibernateProperties.determineHibernateProperties(
                    jpaProperties.getProperties(), new HibernateSettings());
    
            return builder
                    .dataSource(userDataSource)
                    .properties(properties)
                    .packages(new String[]{"wen.multidatasource.domain"})
                    .persistenceUnit("userPersistenceUnit")
                    .build();
        }
    
        @Bean(name = "transactionManagerUser")
        public PlatformTransactionManager transactionManagerUser(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactoryUser(builder).getObject());
        }
    
        @Bean(name = "entityManagerUser")
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactoryUser(builder).getObject().createEntityManager();
        }
    }
    
    • entityManagerFactoryUser : 配置工厂实体
    • transactionManagerUser : 配置事务
    • entityManagerUser : 配置实体
  • 配置实体类:包名:wen.multidatasource.domain:

    User.java:

    package wen.multidatasource.domain;
    
    import lombok.Data;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "t_user")
    @Data
    public class User {
    
        @Id
        @Column(name = "t_id")
        @GeneratedValue
        private Long id;
    
        @Column(name = "t_name")
        private String name;
    
        @Column(name = "t_age")
        private int age;
    
        @Column(name = "t_address")
        private String address;
    
        @Column(name = "t_pwd")
        private String pwd;
    }
    

    Book.java:

    package wen.multidatasource.domain;
    
    import lombok.Data;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "book")
    @Data
    public class Book {
    
        @Id
        @Column(name = "b_id")
        @GeneratedValue
        private Long id;
    
        @Column(name = "b_name")
        private String name;
    
    }
    

    这里需要注意一下:我踩过的坑,实体类对于ID的导入包不要导错

  • 定义dao层:包名wen.multidatasource.dao

    BaseDAO.java:

    package wen.multidatasource.dao;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    
    import java.io.Serializable;
    
    public interface BaseDAO extends JpaRepository, JpaSpecificationExecutor, Serializable {
    }	
    

    BookJPA.java: 所在包:wen.multidatasource.dao.bookjpa
    这里注意,BookJPA.java与UserJPA.java所在的包一定要分开:
    Spring Boot学习笔记(七)SpringBoot:JPA + Druid 多数据源_第2张图片
    BookJPA.java

    package wen.multidatasource.dao.bookjpa;
    
    import wen.multidatasource.dao.BaseDAO;
    import wen.multidatasource.domain.Book;
    
    public interface BookJPA extends BaseDAO {
    }
    
    

    UserJPA.java

    package wen.multidatasource.dao.userjpa;
    
    import wen.multidatasource.dao.BaseDAO;
    import wen.multidatasource.domain.Book;
    
    public interface UserJPA extends BaseDAO {
    }
    
    
  • Controller类:调用了jpa内部的findAll()方法来读取全部数据列表,并通过@RestController注解作用返回Json字符串

    BookController.java:

    package wen.multidatasource.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import wen.multidatasource.dao.bookjpa.BookJPA;
    import wen.multidatasource.domain.Book;
    
    import java.util.List;
    
    @RestController
    @RequestMapping(value = "/book")
    public class BookController {
    
        @Autowired
        private BookJPA bookJPA;
    
        @RequestMapping(value = "/list")
        public List list() {
            return bookJPA.findAll();
        }
    }
    

    UserController.java

    package wen.multidatasource.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import wen.multidatasource.dao.userjpa.UserJPA;
    import wen.multidatasource.domain.User;
    
    import java.util.List;
    
    @RestController
    @RequestMapping(value = "/user")
    public class UserController {
    
        @Autowired
        private UserJPA userJPA;
    
        @RequestMapping("/list")
        public List list() {
            return userJPA.findAll();
        }
    }
    
    
  • 启动成功:访问 http://localhost:8080/book/list 或 http://localhost:8080/user/list 运行结果:

Spring Boot学习笔记(七)SpringBoot:JPA + Druid 多数据源_第3张图片
Spring Boot学习笔记(七)SpringBoot:JPA + Druid 多数据源_第4张图片
下一篇:Spring Boot学习笔记(八)Spring Boot Thymeleaf

你可能感兴趣的:(Java,后端,Spring,Boot学习笔记)