====== Multiple Data Sources ====== - To have multiple data source, you need to write it in code. You cannot do it alone in application.properties (at least up to now (2021/02/08)). - Add multiple @Configuration with @EnableJpaRepositories. During config, add the package location of the entities related to this data source. - We need to add three beans in each of the configuration file to setup the EntityManager, DataSource, and TransactionManager. - Add @Primary for your primary data source's methods/beans. - Put your Entities files on correct package (see below). - Add ''spring-boot-starter-data-jpa'' dependency in your pom.xml ===== Configuration ===== Here is how to config the primary data source. We use Environment here so that we can get the properties settings in application.properties files. You can set them there directly here if you want. Note that we do not store user/password directly in plain text format, so we need to decrypt them with our own Tools class. Note that the EnableJpaRepositories refs name MUST match with our method/bean names. @Configuration @PropertySource({"classpath:application.properties"}) @EnableJpaRepositories( basePackages = "com.exmaple.myapp.repository.primary", entityManagerFactoryRef = "primaryEntityManager", transactionManagerRef = "primaryTransactionManager" ) public class PersistencePrimaryDataConfiguration { @Autowired private Environment env; @Bean @Primary public LocalContainerEntityManagerFactoryBean primaryEntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(primaryDataSource()); em.setPackagesToScan("hk.org.ha.mipo.sopHamisDataExtractor.model.primary"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", env.getProperty("primary.hibernate.ddl-auto")); properties.put("hibernate.dialect", env.getProperty("primary.hibernate.dialect")); properties.put("hibernate.jdbc.batch_size", env.getProperty("primary.hibernate.jdbc.batch_size")); properties.put("hibernate.order_inserts", env.getProperty("primary.hibernate.order_inserts")); properties.put("hibernate.order_updates", env.getProperty("primary.hibernate.order_updates")); properties.put("hibernate.generate_statistics", env.getProperty("primary.hibernate.generate_statistics")); properties.put("hibernate.naming.implicit-strategy", env.getProperty("primary.hibernate.naming.implicit-strategy")); properties.put("hibernate.naming.physical-strategy", env.getProperty("primary.hibernate.naming.physical-strategy")); em.setJpaPropertyMap(properties); return em; } @Primary @Bean public DataSource primaryDataSource() { String encryptedUser = env.getProperty("primary.username"); String encryptedPass = env.getProperty("primary.password"); DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("primary.driverClassName")); dataSource.setUrl(env.getProperty("primary.jdbc.url")); try { dataSource.setUsername(Tools.decrypt(encryptedUser)); dataSource.setPassword(Tools.decrypt(encryptedPass)); } catch (UnsupportedEncodingException e) { //should not happened e.printStackTrace(); } return dataSource; } @Primary @Bean public PlatformTransactionManager primaryTransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(primaryEntityManager().getObject()); return transactionManager; } } A usual setting in the application.properties would be primary.username=%^%*&^&^*&*&ENCODED USERNAME*&*&^(*(*&^&* primary.password=@#$%^&*$%&&&ENCODED PASSWORD^%&*^&!@#$%^&*(* primary.jdbc.url=jdbc:PRIMARY_SERVER_LOCATION:PORT;databaseName=YOUR_DATABASE_NAME primary.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver primary.hibernate.ddl-auto=none primary.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect primary.hibernate.jdbc.batch_size=30 primary.hibernate.order_inserts=true primary.hibernate.order_updates=true primary.hibernate.generate_statistics=false primary.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl primary.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl ===== The Second, Third,... Configuration ===== They are basically the same as your primary data source configuration file, except you do not add @Primary at the methods/beans. ===== Entity Package ===== If you pay attention on the code, you will see ...basePackages = "com.example.myapp.primary",.. ... //and ...em.setPackagesToScan("com.example.myapp.primary"); Here you can actually pass in an array of string to tell Spring which package(s) of your entities is related to this data source. Yes, we use the package to separate the relation to the data sources. Meaning if you have two data sources, you need to have at least two packages for your entities.