SpringBoot多數據源配置詳解

2020-11-07 FastCoder

開發環境:JDK1.8+SpringBoot2.1.4.RELEASE+Oracle

這裡我們假設要使用兩個數據源分別為:master和slave。

  • pom.xml 依賴包

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.github.noraui</groupId> <artifactId>ojdbc7</artifactId> <version>12.1.0.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> </dependencies>

  • application.yml配置

server: port: 50000 ---spring: jpa: hibernate: ddlAuto: update openInView: true showSql: false databasePlatform: org.hibernate.dialect.Oracle10gDialect---# 第一個數據源 master: datasource: driverClassName: oracle.jdbc.driver.OracleDriver url: jdbc:oracle:thin:@localhost:1521/orcl username: t0 password: t0 type: com.zaxxer.hikari.HikariDataSource hikari: minimumIdle: 10 maximumPoolSize: 200 autoCommit: true idleTimeout: 30000 poolName: MasterDatabookHikariCP maxLifetime: 1800000 connectionTimeout: 30000 connectionTestQuery: SELECT 1 FROM DUAL# 第二個數據源 slave: datasource: driverClassName: oracle.jdbc.driver.OracleDriver url: jdbc:oracle:thin:@localhost:1521/orcl username: t1 password: t1 type: com.zaxxer.hikari.HikariDataSource hikari: minimumIdle: 10 maximumPoolSize: 200 autoCommit: true idleTimeout: 30000 poolName: SlaveDatabookHikariCP maxLifetime: 1800000 connectionTimeout: 30000 connectionTestQuery: SELECT 1 FROM DUAL ---# mybatis 配置,分表對應到不同的包中 master: mybatis: config-location: classpath:/MyBatis-conf.xml type-aliases-package: com.pack.domain #master數據源對應的包 mapper-locations: - classpath:/com/pack/mapper/oracle/*.xml #master數據源對應mapper文件slave: mybatis: config-location: classpath:/MyBatis-conf.xml type-aliases-package: com.pack.slave.domain #slave數據源對應的包 mapper-locations: - classpath:/com/pack/slave/mapper/oracle/*.xml #slave數據源對應mapper文件---# jpa相關的配置master: jpa: repos: com.pack.base.repository #master數據源對應的包配置 domain: com.pack.domain #master對應的實體包slave: jpa: repos: com.pack.slave.repository #salve數據源對應的包配置 domain: com.pack.slave.domain #slave對應的實體包

以上就是兩個數據源對應相關的配置了,大家注意看裡面的注釋。接下來我們看mabatis和jpa對應的類相關的配置了,都是固定的配置。

  • 數據源屬性配置對應的java類配置

BaseProperties類

public class BaseDataSourceProperties implements BeanClassLoaderAware, InitializingBean { private ClassLoader classLoader; /** * Name of the datasource. Default to "testdb" when using an embedded database. */ private String name; /** * Whether to generate a random datasource name. */ private boolean generateUniqueName; /** * Fully qualified name of the connection pool implementation to use. By default, it * is auto-detected from the classpath. */ private Class<? extends DataSource> type; /** * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. */ private String driverClassName; /** * JDBC URL of the database. */ private String url; /** * Login username of the database. */ private String username; /** * Login password of the database. */ private String password; /** * JNDI location of the datasource. Class, url, username & password are ignored when * set. */ private String jndiName; /** * Initialize the datasource with available DDL and DML scripts. */ private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED; /** * Platform to use in the DDL or DML scripts (such as schema-${platform}.sql or * data-${platform}.sql). */ private String platform = "all"; /** * Schema (DDL) script resource references. */ private List<String> schema; /** * Username of the database to execute DDL scripts (if different). */ private String schemaUsername; /** * Password of the database to execute DDL scripts (if different). */ private String schemaPassword; /** * Data (DML) script resource references. */ private List<String> data; /** * Username of the database to execute DML scripts (if different). */ private String dataUsername; /** * Password of the database to execute DML scripts (if different). */ private String dataPassword; /** * Whether to stop if an error occurs while initializing the database. */ private boolean continueOnError = false; /** * Statement separator in SQL initialization scripts. */ private String separator = ";"; /** * SQL scripts encoding. */ private Charset sqlScriptEncoding; private EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection.NONE; private Xa xa = new Xa(); private String uniqueName; @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } @Override public void afterPropertiesSet() throws Exception { this.embeddedDatabaseConnection = EmbeddedDatabaseConnection .get(this.classLoader); } /** * Initialize a {@link DataSourceBuilder} with the state of this instance. * @return a {@link DataSourceBuilder} initialized with the customizations defined on * this instance */ public DataSourceBuilder<?> initializeDataSourceBuilder() { return DataSourceBuilder.create(getClassLoader()).type(getType()) .driverClassName(determineDriverClassName()).url(determineUrl()) .username(determineUsername()).password(determinePassword()); } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public boolean isGenerateUniqueName() { return this.generateUniqueName; } public void setGenerateUniqueName(boolean generateUniqueName) { this.generateUniqueName = generateUniqueName; } public Class<? extends DataSource> getType() { return this.type; } public void setType(Class<? extends DataSource> type) { this.type = type; } /** * Return the configured driver or {@code null} if none was configured. * @return the configured driver * @see #determineDriverClassName() */ public String getDriverClassName() { return this.driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } /** * Determine the driver to use based on this configuration and the environment. * @return the driver to use * @since 1.4.0 */ public String determineDriverClassName() { if (StringUtils.hasText(this.driverClassName)) { Assert.state(driverClassIsLoadable(), () -> "Cannot load driver class: " + this.driverClassName); return this.driverClassName; } String driverClassName = null; if (StringUtils.hasText(this.url)) { driverClassName = DatabaseDriver.fromJdbcUrl(this.url).getDriverClassName(); } if (!StringUtils.hasText(driverClassName)) { driverClassName = this.embeddedDatabaseConnection.getDriverClassName(); } if (!StringUtils.hasText(driverClassName)) { throw new DataSourceBeanCreationException( "Failed to determine a suitable driver class", this, this.embeddedDatabaseConnection); } return driverClassName; } private boolean driverClassIsLoadable() { try { ClassUtils.forName(this.driverClassName, null); return true; } catch (UnsupportedClassVersionError ex) { // Driver library has been compiled with a later JDK, propagate error throw ex; } catch (Throwable ex) { return false; } } /** * Return the configured url or {@code null} if none was configured. * @return the configured url * @see #determineUrl() */ public String getUrl() { return this.url; } public void setUrl(String url) { this.url = url; } /** * Determine the url to use based on this configuration and the environment. * @return the url to use * @since 1.4.0 */ public String determineUrl() { if (StringUtils.hasText(this.url)) { return this.url; } String databaseName = determineDatabaseName(); String url = (databaseName != null) ? this.embeddedDatabaseConnection.getUrl(databaseName) : null; if (!StringUtils.hasText(url)) { throw new DataSourceBeanCreationException( "Failed to determine suitable jdbc url", this, this.embeddedDatabaseConnection); } return url; } /** * Determine the name to used based on this configuration. * @return the database name to use or {@code null} * @since 2.0.0 */ public String determineDatabaseName() { if (this.generateUniqueName) { if (this.uniqueName == null) { this.uniqueName = UUID.randomUUID().toString(); } return this.uniqueName; } if (StringUtils.hasLength(this.name)) { return this.name; } if (this.embeddedDatabaseConnection != EmbeddedDatabaseConnection.NONE) { return "testdb"; } return null; } /** * Return the configured username or {@code null} if none was configured. * @return the configured username * @see #determineUsername() */ public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } /** * Determine the username to use based on this configuration and the environment. * @return the username to use * @since 1.4.0 */ public String determineUsername() { if (StringUtils.hasText(this.username)) { return this.username; } if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName())) { return "sa"; } return null; } /** * Return the configured password or {@code null} if none was configured. * @return the configured password * @see #determinePassword() */ public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } /** * Determine the password to use based on this configuration and the environment. * @return the password to use * @since 1.4.0 */ public String determinePassword() { if (StringUtils.hasText(this.password)) { return this.password; } if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName())) { return ""; } return null; } public String getJndiName() { return this.jndiName; } /** * Allows the DataSource to be managed by the container and obtained via JNDI. The * {@code URL}, {@code driverClassName}, {@code username} and {@code password} fields * will be ignored when using JNDI lookups. * @param jndiName the JNDI name */ public void setJndiName(String jndiName) { this.jndiName = jndiName; } public DataSourceInitializationMode getInitializationMode() { return this.initializationMode; } public void setInitializationMode(DataSourceInitializationMode initializationMode) { this.initializationMode = initializationMode; } public String getPlatform() { return this.platform; } public void setPlatform(String platform) { this.platform = platform; } public List<String> getSchema() { return this.schema; } public void setSchema(List<String> schema) { this.schema = schema; } public String getSchemaUsername() { return this.schemaUsername; } public void setSchemaUsername(String schemaUsername) { this.schemaUsername = schemaUsername; } public String getSchemaPassword() { return this.schemaPassword; } public void setSchemaPassword(String schemaPassword) { this.schemaPassword = schemaPassword; } public List<String> getData() { return this.data; } public void setData(List<String> data) { this.data = data; } public String getDataUsername() { return this.dataUsername; } public void setDataUsername(String dataUsername) { this.dataUsername = dataUsername; } public String getDataPassword() { return this.dataPassword; } public void setDataPassword(String dataPassword) { this.dataPassword = dataPassword; } public boolean isContinueOnError() { return this.continueOnError; } public void setContinueOnError(boolean continueOnError) { this.continueOnError = continueOnError; } public String getSeparator() { return this.separator; } public void setSeparator(String separator) { this.separator = separator; } public Charset getSqlScriptEncoding() { return this.sqlScriptEncoding; } public void setSqlScriptEncoding(Charset sqlScriptEncoding) { this.sqlScriptEncoding = sqlScriptEncoding; } public ClassLoader getClassLoader() { return this.classLoader; } public Xa getXa() { return this.xa; } public void setXa(Xa xa) { this.xa = xa; } /** * XA Specific datasource settings. */ public static class Xa { /** * XA datasource fully qualified name. */ private String dataSourceClassName; /** * Properties to pass to the XA data source. */ private Map<String, String> properties = new LinkedHashMap<>(); public String getDataSourceClassName() { return this.dataSourceClassName; } public void setDataSourceClassName(String dataSourceClassName) { this.dataSourceClassName = dataSourceClassName; } public Map<String, String> getProperties() { return this.properties; } public void setProperties(Map<String, String> properties) { this.properties = properties; } } static class DataSourceBeanCreationException extends BeanCreationException { /** * */ private static final long serialVersionUID = 1L; private final BaseDataSourceProperties properties; private final EmbeddedDatabaseConnection connection; DataSourceBeanCreationException(String message, BaseDataSourceProperties properties, EmbeddedDatabaseConnection connection) { super(message); this.properties = properties; this.connection = connection; } public BaseDataSourceProperties getProperties() { return this.properties; } public EmbeddedDatabaseConnection getConnection() { return this.connection; } }}

mybatis對應的base屬性文件

public class BaseMybatisProperties { /** * Config file path. */ private String configLocation; /** * Location of mybatis mapper files. */ private String[] mapperLocations; /** * Package to scan domain objects. */ private String typeAliasesPackage; /** * Package to scan handlers. */ private String typeHandlersPackage; /** * Check the config file exists. */ private boolean checkConfigLocation = false; /** * Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}. */ private ExecutorType executorType; /** * A Configuration object for customize default settings. If * {@link #configLocation} is specified, this property is not used. */ private Configuration configuration; /** * @since 1.1.0 * @return */ public String getConfigLocation() { return this.configLocation; } /** * @since 1.1.0 * @return */ public void setConfigLocation(String configLocation) { this.configLocation = configLocation; } @Deprecated public String getConfig() { return this.configLocation; } @Deprecated public void setConfig(String config) { this.configLocation = config; } public String[] getMapperLocations() { return this.mapperLocations; } public void setMapperLocations(String[] mapperLocations) { this.mapperLocations = mapperLocations; } public String getTypeHandlersPackage() { return this.typeHandlersPackage; } public void setTypeHandlersPackage(String typeHandlersPackage) { this.typeHandlersPackage = typeHandlersPackage; } public String getTypeAliasesPackage() { return this.typeAliasesPackage; } public void setTypeAliasesPackage(String typeAliasesPackage) { this.typeAliasesPackage = typeAliasesPackage; } public boolean isCheckConfigLocation() { return this.checkConfigLocation; } public void setCheckConfigLocation(boolean checkConfigLocation) { this.checkConfigLocation = checkConfigLocation; } public ExecutorType getExecutorType() { return this.executorType; } public void setExecutorType(ExecutorType executorType) { this.executorType = executorType; } public Configuration getConfiguration() { return configuration; } public void setConfiguration(Configuration configuration) { this.configuration = configuration; } public Resource[] resolveMapperLocations() { List<Resource> resources = new ArrayList<Resource>(); if (this.mapperLocations != null) { for (String mapperLocation : this.mapperLocations) { Resource[] mappers; try { mappers = new PathMatchingResourcePatternResolver().getResources(mapperLocation); resources.addAll(Arrays.asList(mappers)); } catch (IOException e) { } } } Resource[] mapperLocations = new Resource[resources.size()]; mapperLocations = resources.toArray(mapperLocations); return mapperLocations; }}

因為我們使用的是Hikari數據源,所以這裡我是直接copy默認系統Hikari的屬性文件。

也就是這個文件:org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 為啥我不直接繼承這個類而是在自己的項目中新建這麼一個類,是因為我發現這個類有這個註解

@ConfigurationProperties(prefix = "spring.datasource")

怕的是它的這個註解會覆蓋我接下來兩個類的註解(我主要是懶得測試,所以直接copy一份無所謂了)。

接下來看看具體master和slave兩個數據源的屬性文件:

  • Properties(jpa和mybatis)文件

@Component@ConfigurationProperties(prefix = "master.datasource")public class MasterDataSourceProperties extends BaseDataSourceProperties {}

@Component@ConfigurationProperties(prefix = "slave.datasource")public class SlaveDataSourceProperties extends BaseDataSourceProperties {}

@Component@ConfigurationProperties(prefix = "master.mybatis")public class MasterMybatisProperties extends BaseMybatisProperties {}

@Component@ConfigurationProperties(prefix = "slave.mybatis")public class SlaveMybatisProperties extends BaseMybatisProperties {}

接下來是數據源的配置了。

  • 數據源配置類

@Configurationpublic class HikariDataSourceConfig { @Bean @Primary public HikariDataSource masterDataSource(MasterDataSourceProperties properties) { HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } @Bean public HikariDataSource slaveDataSource(SlaveDataSourceProperties properties) { HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } @SuppressWarnings("unchecked") protected static <T> T createDataSource(BaseDataSourceProperties properties, Class<? extends DataSource> type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); } }

因為我們配置的是多個數據源所有其中一個數據源必須加入這個註解@Primary

接下來是jpa的EntityManagerFactory工廠的配置了

  • EntityManagerFactory配置

public class EntityManagerFactoryConfig { @Configuration @EnableJpaRepositories(basePackages = { "${master.jpa.repos}" }, entityManagerFactoryRef = "masterEntityManagerFactory", transactionManagerRef = "masterJPATransactionManager") static class MasterEntityManagerFactory { @Resource(name = "masterDataSource") private DataSource masterDataSource; @Value("${master.jpa.domain}") private String masterDomainPkg; @Bean @Primary public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory(EntityManagerFactoryBuilder builder) { Map<String, Object> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", "update"); properties.put("hibernate.id.new_generator_mappings", true); properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName()) ; return builder.dataSource(masterDataSource).packages(masterDomainPkg).persistenceUnit("master") .properties(properties).build(); } @Bean @Primary public PlatformTransactionManager masterJPATransactionManager(EntityManagerFactoryBuilder builder) { JpaTransactionManager tm = new JpaTransactionManager(masterEntityManagerFactory(builder).getObject()); return tm; } } @Configuration @EnableJpaRepositories(basePackages = { "${slave.jpa.repos}" }, entityManagerFactoryRef = "slaveEntityManagerFactory", transactionManagerRef = "slaveJPATransactionManager") @ConditionalOnProperty(name = "multiple.ds.enabled", havingValue = "true") static class SlaveEntityManagerFactory { @Resource(name = "slaveDataSource") private DataSource slaveDataSource; @Value("${slave.jpa.domain}") private String slaveDomainPkg; @Bean public LocalContainerEntityManagerFactoryBean slaveEntityManagerFactory(EntityManagerFactoryBuilder builder) { Map<String, Object> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", "update"); properties.put("hibernate.id.new_generator_mappings", true); properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName()) ; return builder.dataSource(slaveDataSource).packages(slaveDomainPkg).persistenceUnit("slave") .properties(properties).build(); } @Bean public PlatformTransactionManager slaveJPATransactionManager(EntityManagerFactoryBuilder builder) { JpaTransactionManager tm = new JpaTransactionManager(slaveEntityManagerFactory(builder).getObject()); return tm; } }}

  • mybatis SqlSessionFactory工廠配置

public class SqlSessionFactoryConfig { @Configuration static class MasterSqlSessionFactory { @Resource private MasterMybatisProperties properties; @Autowired(required = false) private Interceptor[] interceptors; @Autowired private ResourceLoader resourceLoader = new DefaultResourceLoader(); @Autowired(required = false) private DatabaseIdProvider databaseIdProvider; @Bean public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } factory.setConfiguration(properties.getConfiguration()); if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } return factory.getObject(); } @Bean public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory")SqlSessionFactory sqlSessionFactory) { ExecutorType executorType = this.properties.getExecutorType(); if (executorType != null) { return new SqlSessionTemplate(sqlSessionFactory, executorType); } else { return new SqlSessionTemplate(sqlSessionFactory); } } } @Configuration @ConditionalOnProperty(name = "multiple.ds.enabled", havingValue = "true") static class SlaveSqlSessionFactory { @Resource private SlaveMybatisProperties properties; @Autowired(required = false) private Interceptor[] interceptors; @Autowired private ResourceLoader resourceLoader = new DefaultResourceLoader(); @Autowired(required = false) private DatabaseIdProvider databaseIdProvider; @Bean public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } factory.setConfiguration(properties.getConfiguration()); if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } return factory.getObject(); } @Bean public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory")SqlSessionFactory sqlSessionFactory) { ExecutorType executorType = this.properties.getExecutorType(); if (executorType != null) { return new SqlSessionTemplate(sqlSessionFactory, executorType); } else { return new SqlSessionTemplate(sqlSessionFactory); } } } }

接下來還需要配置mapper相關的配置

  • mapper配置

public class MapperScanConfig { @Configuration @MapperScan(basePackages = {"com.pack.base.mapper"}, sqlSessionTemplateRef = "masterSqlSessionTemplate") static class MasterMapper { } @Configuration @MapperScan(basePackages = {"com.pack.slave.mapper"}, sqlSessionTemplateRef = "slaveSqlSessionTemplate") @ConditionalOnProperty(name = "multiple.ds.enabled", havingValue = "true") static class SlaveMapper { } }

到這裡我們所有的相關配置就完成了,接下來我們只需建立對應的包即可。


MyBatis-conf.xml配置文件內容如下:


測試:

建立com.pack.domain包,然後新建類Users.java

@Entity@Table(name = "T_USERS")@Datapublic class Users { @Id private Long id; private String username ; private String password ; private String realName ; private String phone ; private String idNo ; @Column(length=4000) private String authority ; @Column(columnDefinition="int default 0") private Integer status = 0 ;}

建立包com.pack.slave.domain,然後新建類

@Entity@Table(name = "T_PERSON")@Datapublic class Person{ @Id private Long id; private String name ; private String email ;}

dao我就不寫了。我們啟動伺服器分別在不同的用戶下查看表是否建立,如果都建立了就表示成功。


完畢!!!

給個關注,給個讚唄,謝謝!!!

相關焦點

  • springboot整合mybatis實現配置多數據源
    前言:實際開發中,隨著業務的擴張,使用單一的資料庫顯然有點臃腫,不便管理,經常會實現將不同的業務模塊的數據表結構放在各自的資料庫中,下邊簡單實現sprongboot實現多數據源的配置。一 項目結構:二 涉及到的資料庫:三 springboot中的application.properties文件:本次demo簡單配置下兩個數據源為例。
  • SpringBoot 的多數據源配置
    多數據源SpringBoot 的多數據源開發十分簡單,如果多個數據源的資料庫相同,比如都是 MySQL,那麼依賴是不需要任何改動的,只需要進行多數據源配置即可。如果你新增的資料庫數據源和目前的資料庫不同,記得引入新資料庫的驅動依賴,比如 MySQL 和 PGSQL。
  • 基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 多數據源配置
    但是往往隨著業務量發展,我們通常會進行資料庫拆分或是引入其他資料庫,從而我們需要配置多個數據源。下面基於 SpringBoot+Mybatis ,帶著大家看一下 SpringBoot 中如何配置多數據源。
  • SpringBoot實戰(三):Mybatis配置多數據源
    【前言】 最近接到一個新需求,經過分析後做了相應的設計;其中需要在一個項目中操做不同的數據源;於是進行了相關驗證;在此記錄一下驗證過程。【實戰多數據源】 一、Pom中引入相應的Jar包<!artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version></dependency> 二、主要代碼展示 1、application.properties增加資料庫連接的相關配置
  • springboot環境jpa配置多個數據源流程
    一 簡介開發過程中,我們都需要和資料庫打交道,小項目一個資料庫就可以,代碼也比較簡單,只要連接一個資料庫,本文中,由於業務需求,我們需要連接另一個庫去查詢數據,因此要對舊版本(只實現連接一個庫的jpa)進行改造,使之可以同時連接兩個庫。
  • SpringBoot 配置 MongoDB 多數據源
    SpringBoot 配置 mongodb 多數據源datacenter#----------------------------------------------##end mongodb for spirit3、配置相應的數據源
  • springBoot多數據源的yml配置+指定數據源
    接上一篇yml配置druid: type: com.alibaba.druid.pool.DruidDataSource user: url: jdbc:mysql://localhost:3306/user?
  • springboot配置文件詳解
    關於配置文件springboot有兩種格式的配置文件,即,properties 中的數據是無序的關於配置文件加載順序默認情況下,springboot應用會依次從以下位置加載配置文件:項目根目錄下的自定義配置文件名的方式,與自定義配置文件的方式類似,同時兩個命令可以一起使用。
  • SpringBoot+Mybatis+druid 多數據源配置
    其實配置相當簡單,僅供學習參考,如有不足請賜教。數據源(一)DruidDatasourceConfig.javaDataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource); return dataSourceTransactionManager; }}需要注意三個點:1.兩個連接池指定各自的mapper文件掃碼路徑;2.數據源配置區分開
  • SpringBoot配置多數據源最簡單的解決方案
    一個最簡單的SpringBoot+Mybatis的多數據源解決方案,基於Mysql資料庫。不能用你打我,需要指導可以留言。喜歡可以關注我,不扯淡,還是謝謝你。1.第一步先配置多個數據源信息,在application.properties文件裡面。
  • MyBatis初級實戰之四:druid多數據源
    GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;關於druid多數據源
  • SpringBoot配置數據源及MyBatis分頁的要點
    ,容易出現分頁無效的問題,這種情況常見於自定義數據源的情況。無論哪一種,都需要為數據源設置分頁插件配置。如果使用 SpringBoot 自帶的數據源,則不需要手動設置分頁插件,只需要提供分頁插件配置類即可;如果是自定義的數據源,則必須為其配置分頁插件。
  • 談談SpringBoot數據源加載及其多數據源簡單實現
    業務需求提供所有微服務數據源的圖形化維護功能代碼生成可以根據選擇的數據源加載表等源信息數據源管理要支持動態配置,實時生效 附錄效果圖 實現思路本文提供方法僅供類似簡單業務場景,在生產環境和複雜的業務場景 請使用分庫分表的中間件(例如mycat)或者框架
  • 第二章:springboot配置入門
    springboot讓您儘可能快速的啟動和運行您的項目,在大多數情況下,並不需要我們進行太多的配置就可以完美的讓springboot正常運行。然而往往,在很多時候,springboot的配置並不能滿足於我們的需求,所以此時我們就需要進行一些配置的修改,並且加上我們自己的配置項。
  • 苞米豆-多數據源七夕特別版 2.1.0 發布:全面適配 mybatis-plus
    底層代碼進行了細微的性能優化https://gitee.com/baomidou/dynamic-datasource-spring-boot-starter從2.1.0開始提供對mp的集成,在以前的版本你直接調用的方法是mp提供的內置方法,因其不是我們自己的方法不能切換數據源,你會得到一個NP異常。
  • 一文詳解 SpringBoot 多數據源中的分布式事務
    Java 事務API,允許應用程式執行分布式事務處理——在兩個或多個網絡計算機資源上訪問並且更新數據。JDBC驅動程序的JTA支持極大地增強了數據訪問能力。事務最簡單最直接的目的就是保證數據的有效性,數據的一致性。Atomikos是一個為Java平臺提供增值服務的並且開源類事務管理器。工作原理:分布式事務包括事務管理器和支持XA的資源管理器。
  • 苞米豆-多數據源 2.3.2 發布:支持 spel 從參數獲取數據源
    https://gitee.com/baomidou/dynamic-datasource-spring-boot-starterdynamic-datasource-spring-boot-starter 是一個基於springboot的快速集成多數據源的啟動器。
  • SpringBoot+Atomikos多數據源分布式事務
    physical_naming_strategy這裡配置了兩個數據源,account庫和storage庫數據源配置數據源屬性文件:@Datapublic class BaseDataSourceProperties { private String resourceName ; private String
  • 苞米豆-多數據源 3.2.0 發布:多種特性升級 bug 修復 - OSCHINA...
    簡介dynamic-datasource-spring-boot-starter 是一個基於springboot的快速集成多數據源的啟動器。
  • SpringBoot+Mybatis+ Druid+PageHelper 實現多數據源並分頁
    首先是MasterDataSourceConfig.java這個類,這個是默認的數據源配置類。多數據源配置的時候注意,必須要有一個主數據源,用 @Primary 標誌該 Bean。@MapperScan: 掃描 Mapper 接口並容器管理。需要注意的是sqlSessionFactoryRef 表示定義一個唯一 SqlSessionFactory 實例。