Spring Boot JPA多数据源示例

x33g5p2x  于2022-10-06 转载在 Spring  
字(24.4k)|赞(0)|评价(0)|浏览(997)

在本文中,我们将学习如何在一个典型的Spring Boot Web应用程序中配置多个数据源并连接到多个数据库。我们将使用Spring Boot 2.0.5JPAHibernate 5ThymeleafH2数据库来构建一个简单的Spring Boot多数据源Web应用。
我们知道,如果你有一个单一的数据库,Spring Boot的自动配置是开箱即用的,并通过其属性提供大量的定制选项。但如果你的应用要求对应用配置有更多的控制,你可以关闭特定的自动配置,自己配置组件。

在这篇文章中,我们将逐步学习如何在同一个应用程序中使用多个数据库。如果我们需要连接多个数据库,我们需要配置各种Spring Bean,如DataSourcesTransactionManagersEntityManagerFactoryBeansDataSourceInitializers等,明确配置。

我们将建立什么?

我们将构建一个Spring Boot网络应用,其中security data被存储在一个数据库/模式中,order-related data被存储在另一个数据库/模式中。

让我们看看我们如何在Spring Boot中处理多个数据库,并使用基于Spring Data JPA的应用程序。

使用的工具和技术

  • Spring Boot - 2.0.5.RELEASE
  • JDK - 1.8或更高版本
  • Spring Framework - 5.0.9 RELEASE
  • Spring Data JPA - 2.0.10 RELEASE
  • Hibernate - 5.2.17.Final
  • Maven - 3.2+
  • JPA
  • H2
  • Thymeleaf
  • IDE Eclipse 或 Spring Tool Suite (STS)

创建和导入一个项目

有很多方法可以创建Spring Boot应用程序。最简单的方法是在http://start.spring.io/使用Spring Initializr,它是一个在线Spring Boot应用程序生成器。

看上面的图,我们指定了以下细节。

  • Generate: Maven项目
  • Java Version: 1.8 (默认)
  • Spring Boot:2.0.4
  • Group: net.guards.springboot
  • Artifact: springboot-multiple-datasources
  • Name: springboot-multiple-datasources
  • Description: 一个简单的用户管理应用的Rest API
  • Package Name : net.guards.springboot.springbootmultipledatasources
  • Packaging: jar (这是默认值)
  • Dependencies: Web, JPA, H2, DevTools
    一旦,所有的细节被输入,点击生成项目按钮将生成一个spring boot项目并下载。接下来,解压下载的压缩文件并将其导入你最喜欢的IDE。

项目结构

以下是项目结构 -

pom.xml文件

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>net.guides.springboot</groupId>
  7. <artifactId>springboot-multiple-datasources</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. <packaging>jar</packaging>
  10. <name>springboot-multiple-datasources</name>
  11. <description>Demo project for Spring Boot</description>
  12. <parent>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-parent</artifactId>
  15. <version>2.0.5.RELEASE</version>
  16. <relativePath /> <!-- lookup parent from repository -->
  17. </parent>
  18. <properties>
  19. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  20. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  21. <java.version>1.8</java.version>
  22. </properties>
  23. <dependencies>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-test</artifactId>
  27. <scope>test</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-devtools</artifactId>
  32. <optional>true</optional>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-configuration-processor</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-data-jpa</artifactId>
  42. </dependency>
  43. <dependency>
  44. <groupId>org.springframework.boot</groupId>
  45. <artifactId>spring-boot-starter-web</artifactId>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  50. </dependency>
  51. <dependency>
  52. <groupId>mysql</groupId>
  53. <artifactId>mysql-connector-java</artifactId>
  54. </dependency>
  55. <dependency>
  56. <groupId>com.h2database</groupId>
  57. <artifactId>h2</artifactId>
  58. </dependency>
  59. </dependencies>
  60. <build>
  61. <plugins>
  62. <plugin>
  63. <groupId>org.springframework.boot</groupId>
  64. <artifactId>spring-boot-maven-plugin</artifactId>
  65. </plugin>
  66. </plugins>
  67. </build>
  68. </project>

确保我们在classpath上有JPAThymeleaf H2启动器。
接下来的步骤非常重要,请看一下。

排除自动配置类

让我们关闭DataSource/JPA的自动配置功能。由于我们要明确配置数据库相关的bean,我们将通过排除AutoConfiguration类来关闭DataSource/JPA的自动配置。

  1. package net.guides.springboot.springbootmultipledatasources;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  5. import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
  6. import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
  7. import org.springframework.transaction.annotation.EnableTransactionManagement;
  8. @SpringBootApplication(
  9. exclude = { DataSourceAutoConfiguration.class,
  10. HibernateJpaAutoConfiguration.class,
  11. DataSourceTransactionManagerAutoConfiguration.class })
  12. @EnableTransactionManagement
  13. public class SpringbootMultipleDatasourcesApplication {
  14. public static void main(String[] args) {
  15. SpringApplication.run(SpringbootMultipleDatasourcesApplication.class, args);
  16. }
  17. }

一旦我们关闭了自动配置,我们就需要通过使用@EnableTransactionManagement注解来明确启用TransactionManagement。

配置多个数据源属性

H2数据库配置

让我们来配置H2数据源属性。在application.properties文件中配置安全和订单的数据库连接参数.

  1. debug=true
  2. datasource.security.driver-class-name=org.h2.Driver
  3. datasource.security.url=jdbc:h2:mem:securitydb;DB_CLOSE_DELAY=-1
  4. datasource.security.username=sa
  5. datasource.security.password=
  6. datasource.security.initialize=true
  7. datasource.orders.driver-class-name=org.h2.Driver
  8. datasource.orders.url=jdbc:h2:mem:ordersdb;DB_CLOSE_DELAY=-1
  9. datasource.orders.username=sa
  10. datasource.orders.password=
  11. datasource.orders.initialize=true
  12. spring.jpa.hibernate.ddl-auto=update
  13. spring.jpa.show-sql=true

MySQL数据库配置

我们使用H2数据库来快速建立应用程序,但你也可以在application.properties文件中替换以下配置来使用MySQL数据库进行生产。

注意,我们使用了自定义属性键来配置两个数据源属性。
在下一步,我们将创建一个与安全相关的JPA实体和一个JPA资源库。

创建JPA实体--用户和地址

  1. /**
  2. *
  3. */
  4. package net.guides.springboot.springbootmultipledatasources.security.entities;
  5. import java.util.Set;
  6. import javax.persistence.Column;
  7. import javax.persistence.Entity;
  8. import javax.persistence.GeneratedValue;
  9. import javax.persistence.GenerationType;
  10. import javax.persistence.Id;
  11. import javax.persistence.OneToMany;
  12. import javax.persistence.Table;
  13. /**
  14. * @author Ramesh Fadatare
  15. *
  16. */
  17. @Entity
  18. @Table(name="USERS")
  19. public class User
  20. {
  21. @Id @GeneratedValue(strategy=GenerationType.AUTO)
  22. private Integer id;
  23. @Column(nullable=false)
  24. private String name;
  25. @Column(nullable=false, unique=true)
  26. private String email;
  27. private boolean disabled;
  28. @OneToMany(mappedBy="user")
  29. private Set<Address> addresses;
  30. public User()
  31. {
  32. }
  33. public User(Integer id, String name, String email)
  34. {
  35. this.id = id;
  36. this.name = name;
  37. this.email = email;
  38. }
  39. public User(Integer id, String name, String email, boolean disabled)
  40. {
  41. this.id = id;
  42. this.name = name;
  43. this.email = email;
  44. this.disabled = disabled;
  45. }
  46. public Integer getId()
  47. {
  48. return id;
  49. }
  50. public void setId(Integer id)
  51. {
  52. this.id = id;
  53. }
  54. public String getName()
  55. {
  56. return name;
  57. }
  58. public void setName(String name)
  59. {
  60. this.name = name;
  61. }
  62. public String getEmail()
  63. {
  64. return email;
  65. }
  66. public void setEmail(String email)
  67. {
  68. this.email = email;
  69. }
  70. public boolean isDisabled()
  71. {
  72. return disabled;
  73. }
  74. public void setDisabled(boolean disabled)
  75. {
  76. this.disabled = disabled;
  77. }
  78. public Set<Address> getAddresses()
  79. {
  80. return addresses;
  81. }
  82. public void setAddresses(Set<Address> addresses)
  83. {
  84. this.addresses = addresses;
  85. }
  86. }

Address.java

  1. package net.guides.springboot.springbootmultipledatasources.security.entities;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.GenerationType;
  6. import javax.persistence.Id;
  7. import javax.persistence.JoinColumn;
  8. import javax.persistence.ManyToOne;
  9. import javax.persistence.Table;
  10. /**
  11. * @author Ramesh Fadatare
  12. *
  13. */
  14. @Entity
  15. @Table(name="ADDRESSES")
  16. public class Address
  17. {
  18. @Id @GeneratedValue(strategy=GenerationType.AUTO)
  19. private Integer id;
  20. @Column(nullable=false)
  21. private String city;
  22. @ManyToOne
  23. @JoinColumn(name="user_id")
  24. private User user;
  25. public Integer getId()
  26. {
  27. return id;
  28. }
  29. public void setId(Integer id)
  30. {
  31. this.id = id;
  32. }
  33. public String getCity()
  34. {
  35. return city;
  36. }
  37. public void setCity(String city)
  38. {
  39. this.city = city;
  40. }
  41. public User getUser()
  42. {
  43. return user;
  44. }
  45. public void setUser(User user)
  46. {
  47. this.user = user;
  48. }
  49. }

Spring JPA存储库 - UserRepository.java

  1. /**
  2. *
  3. */
  4. package net.guides.springboot.springbootmultipledatasources.security.repositories;
  5. import org.springframework.data.jpa.repository.JpaRepository;
  6. import net.guides.springboot.springbootmultipledatasources.security.entities.User;
  7. /**
  8. * @author Ramesh Fadatare
  9. *
  10. */
  11. public interface UserRepository extends JpaRepository<User, Integer>
  12. {
  13. }

创建JPA实体--Order和OrderItem

  1. /**
  2. *
  3. */
  4. package net.guides.springboot.springbootmultipledatasources.orders.entities;
  5. import java.util.Set;
  6. import javax.persistence.Column;
  7. import javax.persistence.Entity;
  8. import javax.persistence.GeneratedValue;
  9. import javax.persistence.GenerationType;
  10. import javax.persistence.Id;
  11. import javax.persistence.OneToMany;
  12. import javax.persistence.Table;
  13. /**
  14. * @author Ramesh Fadatare
  15. *
  16. */
  17. @Entity
  18. @Table(name="ORDERS")
  19. public class Order
  20. {
  21. @Id @GeneratedValue(strategy=GenerationType.AUTO)
  22. private Integer id;
  23. @Column(nullable=false, name="cust_name")
  24. private String customerName;
  25. @Column(nullable=false, name="cust_email")
  26. private String customerEmail;
  27. @OneToMany(mappedBy="order")
  28. private Set<OrderItem> orderItems;
  29. public Integer getId() {
  30. return id;
  31. }
  32. public void setId(Integer id) {
  33. this.id = id;
  34. }
  35. public String getCustomerName() {
  36. return customerName;
  37. }
  38. public void setCustomerName(String customerName) {
  39. this.customerName = customerName;
  40. }
  41. public String getCustomerEmail() {
  42. return customerEmail;
  43. }
  44. public void setCustomerEmail(String customerEmail) {
  45. this.customerEmail = customerEmail;
  46. }
  47. public Set<OrderItem> getOrderItems()
  48. {
  49. return orderItems;
  50. }
  51. public void setOrderItems(Set<OrderItem> orderItems)
  52. {
  53. this.orderItems = orderItems;
  54. }
  55. }

OrderItem.java

  1. package net.guides.springboot.springbootmultipledatasources.orders.entities;
  2. import javax.persistence.Entity;
  3. import javax.persistence.GeneratedValue;
  4. import javax.persistence.GenerationType;
  5. import javax.persistence.Id;
  6. import javax.persistence.JoinColumn;
  7. import javax.persistence.ManyToOne;
  8. import javax.persistence.Table;
  9. /**
  10. * @author Ramesh Fadatare
  11. *
  12. */
  13. @Entity
  14. @Table(name="ORDER_ITEMS")
  15. public class OrderItem
  16. {
  17. @Id @GeneratedValue(strategy=GenerationType.AUTO)
  18. private Integer id;
  19. private String productCode;
  20. private int quantity;
  21. @ManyToOne
  22. @JoinColumn(name="order_id")
  23. private Order order;
  24. public Integer getId()
  25. {
  26. return id;
  27. }
  28. public void setId(Integer id)
  29. {
  30. this.id = id;
  31. }
  32. public String getProductCode()
  33. {
  34. return productCode;
  35. }
  36. public void setProductCode(String productCode)
  37. {
  38. this.productCode = productCode;
  39. }
  40. public int getQuantity()
  41. {
  42. return quantity;
  43. }
  44. public void setQuantity(int quantity)
  45. {
  46. this.quantity = quantity;
  47. }
  48. public Order getOrder()
  49. {
  50. return order;
  51. }
  52. public void setOrder(Order order)
  53. {
  54. this.order = order;
  55. }
  56. }

Spring JPA Repository - OrderRepository.java

  1. /**
  2. *
  3. */
  4. package net.guides.springboot.springbootmultipledatasources.orders.repositories;
  5. import org.springframework.data.jpa.repository.JpaRepository;
  6. import net.guides.springboot.springbootmultipledatasources.orders.entities.Order;
  7. /**
  8. * @author Ramesh Fadatare
  9. *
  10. */
  11. public interface OrderRepository extends JpaRepository<Order, Integer>{
  12. }

初始化样本数据 - security-data.sql脚本

创建SQL脚本来初始化样本数据。在src/main/resources文件夹中创建security-data.sql脚本,用样本数据初始化USERS表。

  1. delete from addresses;
  2. delete from users;
  3. insert into users(id, name, email,disabled) values(1,'John Cena','john@gmail.com', false);
  4. insert into users(id, name, email,disabled) values(2,'Salman Khan','salman@gmail.com', false);
  5. insert into users(id, name, email,disabled) values(3,'Amitr Khan','amir@gmail.com', true);
  6. insert into addresses(id,city,user_id) values(1, 'Pune',1);
  7. insert into addresses(id,city,user_id) values(2, 'Landon',1);
  8. insert into addresses(id,city,user_id) values(3, 'Newyork',2);
  9. insert into addresses(id,city,user_id) values(4, 'Mumbai',3);
  10. insert into addresses(id,city,user_id) values(6, 'Washington',3);

初始化样本数据 - orders-data.sql脚本

src/main/resources文件夹中创建orders-data.sql脚本,用样本数据初始化ORDERS表。

  1. delete from order_items;
  2. delete from orders;
  3. insert into orders(id, cust_name, cust_email) values(1,'John Cena','john@gmail.com');
  4. insert into orders(id, cust_name, cust_email) values(2,'Salman Khan','salman@gmail.com');
  5. insert into orders(id, cust_name, cust_email) values(3,'Amir Khan','amir@gmail.com');
  6. insert into order_items(id, productcode,quantity,order_id) values(1,'order item1', 2, 1);
  7. insert into order_items(id, productcode,quantity,order_id) values(2,'order item2', 1, 1);
  8. insert into order_items(id, productcode,quantity,order_id) values(3,'order item3', 5, 1);
  9. insert into order_items(id, productcode,quantity,order_id) values(4,'order item4', 2, 2);
  10. insert into order_items(id, productcode,quantity,order_id) values(5,'order item5', 1, 2);

创建安全数据源配置 - SecurityDataSourceConfig.java

创建SecurityDataSourceConfig.java配置类。我们将通过连接SecurityDataSourceConfig.java中的安全数据库来配置Spring Bean,如DataSourceTransactionManagerEntityManagerFactoryBeanDataSourceInitializer

  1. package net.guides.springboot.springbootmultipledatasources.config;
  2. import java.util.Properties;
  3. import javax.persistence.EntityManagerFactory;
  4. import javax.sql.DataSource;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
  7. import org.springframework.boot.context.properties.ConfigurationProperties;
  8. import org.springframework.boot.jdbc.DataSourceBuilder;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.core.env.Environment;
  12. import org.springframework.core.io.ClassPathResource;
  13. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  14. import org.springframework.jdbc.datasource.init.DataSourceInitializer;
  15. import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
  16. import org.springframework.orm.jpa.JpaTransactionManager;
  17. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  18. import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  19. import org.springframework.transaction.PlatformTransactionManager;
  20. /**
  21. * @author Ramesh Fadatare
  22. *
  23. */
  24. @Configuration
  25. @EnableJpaRepositories(
  26. basePackages = "net.guides.springboot.springbootmultipledatasources.security.repositories",
  27. entityManagerFactoryRef = "securityEntityManagerFactory",
  28. transactionManagerRef = "securityTransactionManager"
  29. )
  30. public class SecurityDataSourceConfig
  31. {
  32. @Autowired
  33. private Environment env;
  34. @Bean
  35. @ConfigurationProperties(prefix="datasource.security")
  36. public DataSourceProperties securityDataSourceProperties() {
  37. return new DataSourceProperties();
  38. }
  39. @Bean
  40. public DataSource securityDataSource() {
  41. DataSourceProperties securityDataSourceProperties = securityDataSourceProperties();
  42. return DataSourceBuilder.create()
  43. .driverClassName(securityDataSourceProperties.getDriverClassName())
  44. .url(securityDataSourceProperties.getUrl())
  45. .username(securityDataSourceProperties.getUsername())
  46. .password(securityDataSourceProperties.getPassword())
  47. .build();
  48. }
  49. @Bean
  50. public PlatformTransactionManager securityTransactionManager()
  51. {
  52. EntityManagerFactory factory = securityEntityManagerFactory().getObject();
  53. return new JpaTransactionManager(factory);
  54. }
  55. @Bean
  56. public LocalContainerEntityManagerFactoryBean securityEntityManagerFactory()
  57. {
  58. LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
  59. factory.setDataSource(securityDataSource());
  60. factory.setPackagesToScan(new String[]{"net.guides.springboot.springbootmultipledatasources.security.entities"});
  61. factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
  62. Properties jpaProperties = new Properties();
  63. jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
  64. jpaProperties.put("hibernate.show-sql", env.getProperty("spring.jpa.show-sql"));
  65. factory.setJpaProperties(jpaProperties);
  66. return factory;
  67. }
  68. @Bean
  69. public DataSourceInitializer securityDataSourceInitializer()
  70. {
  71. DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
  72. dataSourceInitializer.setDataSource(securityDataSource());
  73. ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
  74. databasePopulator.addScript(new ClassPathResource("security-data.sql"));
  75. dataSourceInitializer.setDatabasePopulator(databasePopulator);
  76. dataSourceInitializer.setEnabled(env.getProperty("datasource.security.initialize", Boolean.class, false));
  77. return dataSourceInitializer;
  78. }
  79. }

请注意,你已经通过使用@ConfigurationProperties(prefix="datasource.security")DataSourceBuilder流畅的API来创建DataSource Bean,将datasource.security.* properties填充到DataSourceProperties中。

在创建LocalContainerEntityManagerFactoryBean Bean时,你已经配置了名为net.guides.springboot.springbootmultipledatasources.security.entities的包来扫描JPA实体。你已经配置了DataSourceInitializer Bean来初始化来自security-data.sql的样本数据。
最后,我们通过使用@EnableJpaRepositories注解来启用Spring Data JPA支持。由于我们将有多个EntityManagerFactoryTransactionManager豆,我们通过指向各自的豆名来配置entityManagerFactoryReftransactionManagerRef的豆ID。我们还配置了basePackages属性,以指示在哪里寻找Spring Data JPA的仓库(包)。

创建安全数据源配置 - OrdersDataSourceConfig.java

创建OrdersDataSourceConfig.java配置类。与SecurityDataSourceConfig.java类似,你将创建OrdersDataSourceConfig.java,但将其指向订单数据库。

  1. package net.guides.springboot.springbootmultipledatasources.config;
  2. import java.util.Properties;
  3. import javax.persistence.EntityManagerFactory;
  4. import javax.sql.DataSource;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
  7. import org.springframework.boot.context.properties.ConfigurationProperties;
  8. import org.springframework.boot.jdbc.DataSourceBuilder;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.core.env.Environment;
  12. import org.springframework.core.io.ClassPathResource;
  13. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  14. import org.springframework.jdbc.datasource.init.DataSourceInitializer;
  15. import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
  16. import org.springframework.orm.jpa.JpaTransactionManager;
  17. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  18. import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  19. import org.springframework.transaction.PlatformTransactionManager;
  20. /**
  21. * @author Ramesh Fadatare
  22. *
  23. */
  24. @Configuration
  25. @EnableJpaRepositories(
  26. basePackages = "net.guides.springboot.springbootmultipledatasources.orders.repositories",
  27. entityManagerFactoryRef = "ordersEntityManagerFactory",
  28. transactionManagerRef = "ordersTransactionManager"
  29. )
  30. public class OrdersDataSourceConfig {
  31. @Autowired
  32. private Environment env;
  33. @Bean
  34. @ConfigurationProperties(prefix = "datasource.orders")
  35. public DataSourceProperties ordersDataSourceProperties() {
  36. return new DataSourceProperties();
  37. }
  38. @Bean
  39. public DataSource ordersDataSource() {
  40. DataSourceProperties primaryDataSourceProperties = ordersDataSourceProperties();
  41. return DataSourceBuilder.create()
  42. .driverClassName(primaryDataSourceProperties.getDriverClassName())
  43. .url(primaryDataSourceProperties.getUrl())
  44. .username(primaryDataSourceProperties.getUsername())
  45. .password(primaryDataSourceProperties.getPassword())
  46. .build();
  47. }
  48. @Bean
  49. public PlatformTransactionManager ordersTransactionManager() {
  50. EntityManagerFactory factory = ordersEntityManagerFactory().getObject();
  51. return new JpaTransactionManager(factory);
  52. }
  53. @Bean
  54. public LocalContainerEntityManagerFactoryBean ordersEntityManagerFactory() {
  55. LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
  56. factory.setDataSource(ordersDataSource());
  57. factory.setPackagesToScan(new String[] {
  58. "net.guides.springboot.springbootmultipledatasources.orders.entities"
  59. });
  60. factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
  61. Properties jpaProperties = new Properties();
  62. jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
  63. jpaProperties.put("hibernate.show-sql", env.getProperty("spring.jpa.show-sql"));
  64. factory.setJpaProperties(jpaProperties);
  65. return factory;
  66. }
  67. @Bean
  68. public DataSourceInitializer ordersDataSourceInitializer() {
  69. DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
  70. dataSourceInitializer.setDataSource(ordersDataSource());
  71. ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
  72. databasePopulator.addScript(new ClassPathResource("orders-data.sql"));
  73. dataSourceInitializer.setDatabasePopulator(databasePopulator);
  74. dataSourceInitializer.setEnabled(env.getProperty("datasource.orders.initialize", Boolean.class, false));
  75. return dataSourceInitializer;
  76. }
  77. }

创建UserOrdersService.java

  1. package net.guides.springboot.springbootmultipledatasources.services;
  2. import java.util.List;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Service;
  5. import org.springframework.transaction.annotation.Transactional;
  6. import net.guides.springboot.springbootmultipledatasources.orders.entities.Order;
  7. import net.guides.springboot.springbootmultipledatasources.orders.repositories.OrderRepository;
  8. import net.guides.springboot.springbootmultipledatasources.security.entities.User;
  9. import net.guides.springboot.springbootmultipledatasources.security.repositories.UserRepository;
  10. /**
  11. * @author Ramesh Fadatare
  12. *
  13. */
  14. @Service
  15. public class UserOrdersService
  16. {
  17. @Autowired
  18. private OrderRepository orderRepository;
  19. @Autowired
  20. private UserRepository userRepository;
  21. @Transactional(transactionManager="securityTransactionManager")
  22. public List<User> getUsers()
  23. {
  24. return userRepository.findAll();
  25. }
  26. @Transactional(transactionManager="ordersTransactionManager")
  27. public List<Order> getOrders()
  28. {
  29. return orderRepository.findAll();
  30. }
  31. }

创建HomeController.java

  1. packagenet.guides.springboot.springbootmultipledatasources.controllers;
  2. importorg.springframework.beans.factory.annotation.Autowired;
  3. importorg.springframework.stereotype.Controller;
  4. importorg.springframework.ui.Model;
  5. importorg.springframework.web.bind.annotation.RequestMapping;
  6. importorg.springframework.web.bind.annotation.RequestMethod;
  7. importnet.guides.springboot.springbootmultipledatasources.services.UserOrdersService;
  8. /*** @author Ramesh Fadatare**/@ControllerpublicclassHomeController{
  9. @AutowiredprivateUserOrdersServiceuserOrdersService;
  10. @RequestMapping(value={"/", "/app/users"}, method=RequestMethod.GET)
  11. publicStringgetUsers(Modelmodel)
  12. {
  13. model.addAttribute("users", userOrdersService.getUsers());
  14. model.addAttribute("orders", userOrdersService.getOrders());
  15. return"users";
  16. }
  17. }

对多个数据源使用OpenEntityManagerInViewFilter

让我们来看看如何使用OpenEntityManagerInViewFilter在渲染视图时启用JPA实体LAZY关联集合的懒惰加载,你需要注册OpenEntityManagerInViewFilter豆。

  1. /**
  2. *
  3. */
  4. package net.guides.springboot.springbootmultipledatasources.config;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
  8. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  9. /**
  10. * @author Ramesh Fadatare
  11. *
  12. */
  13. @Configuration
  14. public class WebMvcConfig extends WebMvcConfigurerAdapter
  15. {
  16. @Bean
  17. public OpenEntityManagerInViewFilter securityOpenEntityManagerInViewFilter()
  18. {
  19. OpenEntityManagerInViewFilter osivFilter = new OpenEntityManagerInViewFilter();
  20. osivFilter.setEntityManagerFactoryBeanName("securityEntityManagerFactory");
  21. return osivFilter;
  22. }
  23. @Bean
  24. public OpenEntityManagerInViewFilter ordersOpenEntityManagerInViewFilter()
  25. {
  26. OpenEntityManagerInViewFilter osivFilter = new OpenEntityManagerInViewFilter();
  27. osivFilter.setEntityManagerFactoryBeanName("ordersEntityManagerFactory");
  28. return osivFilter;
  29. }
  30. }

由于我们正在建立一个Web应用程序,所以该方法返回 users.html 视图。

创建Thymeleaf页面 - users.html

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml"
  3. xmlns:th="http://www.thymeleaf.org">
  4. <head>
  5. <title>SpringBoot</title>
  6. </head>
  7. <body>
  8. <div style="width: 20%; float:left">
  9. <h1>Users</h1>
  10. <hr/>
  11. <div th:each="user : ${users}">
  12. <h2>Name: <span th:text="${user.name}">Name</span></h2>
  13. <h4>Addresses</h4>
  14. <div th:each="addr : ${user.addresses}">
  15. <p th:text="${addr.city}">City</p>
  16. </div>
  17. </div>
  18. </div>
  19. <div style="width: 80%; float:right">
  20. <h1>Orders</h1>
  21. <hr/>
  22. <div th:each="order : ${orders}">
  23. <h2>Customer Name: <span th:text="${order.customerName}">customerName</span></h2>
  24. <h4>Order Items</h4>
  25. <div th:each="item : ${order.orderItems}">
  26. <p th:text="${item.productCode}">productCode</p>
  27. </div>
  28. </div>
  29. </div>
  30. </body>
  31. </html>

运行一个应用程序

SpringbootMultipleDatasourcesApplication.java是一个入口点,所以在你的IDE中右击并选择运行,将在8080端口启动嵌入式tomcat服务器。

在浏览器中点击http://localhost:8080/链接将在浏览器中显示以下网页。

输出

就这样,我完成了一个带有多个数据源的Spring Boot Web应用程序的开发。

在我的GitHub仓库下载这个例子的源代码:https://github.com/RameshMF/springboot-jpa-multiple-datasources

相关文章