近期公司要上线3.0版本,需要将2.0的数据迁移到3.0中继续沿用,由于3.0的数据库相比2.0.的数据库改动很大,最主要的是2.0数据库的主键为自然数自增主键,而3.0数据库的主键为UUID2,所以只能使用程序动态迁移!
本教程使用的持久化框架为JPA,所以数据源也是基于JPA。采用的是SpringBoot2 + SpringDataJPA + MySQL + 双数据源!
1、主从库分离(数据库读写分离)
2、数据迁移
3、系统版本升级,数据库升级到另外一款
- spring:
- jpa:
- hibernate:
- ddl-auto: create
- naming:
- physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
- implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
- open-in-view: true
- show-sql: true
- generate-ddl: true
-
-
- datasource: #database
- primary: # 3.0 Datasource
- jdbc-url: jdbc:mysql://127.0.0.1:3306/gtu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
- username: root
- password: 123456
-
- secondary: # 2.0 Datasource
- jdbc-url: jdbc:mysql://127.0.0.1:3306/gtu-not-completed?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
- username: root
- password: 123456
注:配置文件中需要指定两个数据源,这里在配置的时候是没有自动提示的,因为这是我们自定义的,需要在程序中动态读取。
- @Configuration
- public class DataSourceConfig {
-
-
- @Bean(name = "primaryDataSource")
- @Qualifier("primaryDataSource")
- @Primary
- @ConfigurationProperties(prefix = "spring.datasource.primary")
- public DataSource primaryDataSource() {
- return DataSourceBuilder.create().build();
- }
-
- @Bean(name = "secondaryDataSource")
- @Qualifier("secondaryDataSource")
- @ConfigurationProperties(prefix = "spring.datasource.secondary")
- public DataSource secondaryDataSource() {
- return DataSourceBuilder.create().build();
- }
-
- }
注解解释:
@Configuration:SpringBoot启动将该类作为配置类,同配置文件一起加载
@Bean:将该实体注入到IOC容器中
@Qualifier:指定数据源名称,与Bean中的name属性原理相同,主要是为了确保注入成功
@Primary:指定主数据源
@ConfigurationProperties:将配置文件中的数据源读取进到方法中,进行build
(1)主数据源(对应DataSourceConfig类中的primaryDataSource)
- @Configuration
- @EnableTransactionManagement
- @EnableJpaRepositories(
- entityManagerFactoryRef = "entityManagerFactoryPrimary",
- transactionManagerRef = "transactionManagerPrimary",
- basePackages = {"com.gtcloud.repository"}) // 指定该数据源操作的DAO接口包
- public class PrimaryConfig {
-
- @Autowired
- @Qualifier("primaryDataSource")
- private DataSource primaryDataSource;
-
- @Primary
- @Bean(name = "entityManagerPrimary")
- public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
- return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
- }
-
- @Primary
- @Bean(name = "entityManagerFactoryPrimary")
- public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
- return builder
- .dataSource(primaryDataSource)
- .properties(getVendorProperties())
- .packages("com.gtcloud.model") //设置实体类所在位置
- .persistenceUnit("primaryPersistenceUnit")
- .build();
- }
-
- private Map getVendorProperties() {
- HashMap<String, Object> properties = new HashMap<>();
- properties.put("hibernate.dialect",
- env.getProperty("hibernate.dialect"));
- properties.put("hibernate.ddl-auto",
- "create");
- properties.put("hibernate.physical_naming_strategy",
- "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
- properties.put("hibernate.implicit_naming_strategy",
- "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
- return properties;
- }
-
- @Autowired
- private Environment env;
-
- @Primary
- @Bean(name = "transactionManagerPrimary")
- public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
- return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
- }
-
- }
-
(2)从(次)数据源
- @Configuration
- @EnableTransactionManagement
- @EnableJpaRepositories(
- entityManagerFactoryRef = "entityManagerFactorySecondary",
- transactionManagerRef = "transactionManagerSecondary",
- basePackages = {"com.gtmove.repository"}) //设置DAO接口层所在包位置
- public class SecondaryConfig {
-
- @Autowired
- @Qualifier("secondaryDataSource")
- private DataSource secondaryDataSource;
-
- @Bean(name = "entityManagerSecondary")
- public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
- return entityManagerFactorySecondary(builder).getObject().createEntityManager();
- }
-
- @Bean(name = "entityManagerFactorySecondary")
- public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
- return builder
- .dataSource(secondaryDataSource)
- .properties(getVendorProperties())
- .packages("com.gtmove.model") //设置实体类所在包的位置
- .persistenceUnit("primaryPersistenceUnit")
- .build();
- }
-
- private Map getVendorProperties() {
- HashMap<String, Object> properties = new HashMap<>();
- properties.put("hibernate.hbm2ddl.auto",
- env.getProperty("hibernate.hbm2ddl.auto"));
- properties.put("hibernate.ddl-auto",
- env.getProperty("update"));
- properties.put("hibernate.dialect",
- env.getProperty("hibernate.dialect"));
- properties.put("hibernate.physical_naming_strategy",
- "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
- properties.put("hibernate.implicit_naming_strategy",
- "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
- return properties;
- }
-
- @Autowired
- private Environment env;
-
- @Bean(name = "transactionManagerSecondary")
- PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
- return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
- }
- }
-
这两个类主要配置每个数据源,包括事务管理器、以及实体管理器等配置。
注:必须要指定DAO接口所在的包以及实体类所在的包。每个数据源主要操作它指定的资源(DAO接口CURD、实体类)
1、SpringBoot启动类必须关闭 --程序启动加载的仓库(@EnableJpaRepositories),因为在数据源配置类中已经开启了。如果没有去掉,程序会跑不起来!
- @SpringBootApplication(scanBasePackages = {""}) // 指定加载程序主包,存在默认值【可选】
- //@EntityScan({""})
- //@EnableJpaRepositories(basePackages = {""})
- public class Gt3datamoverApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(Gt3datamoverApplication.class, args);
- }
-
- }
2、如果需要对数据源连接的表进行DDL(正向生成表、程序启动动态更新表),需要在PrimaryConfig类中 /SecondaryConfig类中的getVendorProperties()方法中进行手动设置(此教程都已设置好了!)