springboot整合mysql集_【总结+转
载】SpringBoot+JPA+MyS。。。
==写在开始
MySQL 集+读写分离⽅案有多种选择,可参考 浅谈MySQL集⾼可⽤架构 ,
这⾥选择的是使⽤MySQL官⽅的MySQL Cluster⽅案==
⼀、MySQL Cluster 集配置简介
服务器
Cluster⾓⾊
系统⾓⾊
192.168.2.150
管理节点
192.168.2.151
数据节点(NDBD) & SQL节点(mysqld api)
写服务
192.168.2.152
数据节点(NDBD) & SQL节点(mysqld api)
读服务
为了测试需要,因此在2.151 & 2.152上分别搭建了cluster中的数据节点(ndbd节点服务)和SQL节点(mysqld服务),如果条件允许可以做出以下类似配置
集中⾓⾊ 系统中⾓⾊
服务器 | Cluster⾓⾊ | 系统⾓⾊
---|--- | ---
192.168.2.150 | 管理节点 | ⽆
192.168.2.151 | SQL节点(mysqld api) | 写服务
192.168.2.152 | SQL节点(mysqld api) | 读服务
192.168.2.153 | 数据节点(NDBD) | ⽆
192.168.2.154 | 数据节点(NDBD) | ⽆
⼆、项⽬使⽤的持久层
在SpringBoot项⽬上持久层使⽤的是Spring-Data-JPA,连接的数据库是⼀个MySQL Cluster搭建的集环境;
其中
jdbc:mysql://192.168.2.151:3306/fake-store?useSSL=false&useUnicode=yes&characterEncoding=utf-8
连接的SQL节点⽤作写服务,
jdbc:mysql://192.168.2.152:3306/fake-store?useSSL=false&useUnicode=yes&characterEncoding=utf-8
连接的SQL节点⽤作读服务。
三、相关关键字
AOP拦截动态切换数据源、AbstractRoutingDataSource、
Spring⽀持的数据源路由,JPA 作为持久化框架相关的EntityManager、EntityManagerFactory、JpaTransactionManager 四、定义⼀个数据源类型和数据源上下⽂⼯具类
数据源类型⽤于标⽰数据源类型及作⽤
public enum DataSourceType {
WRITE("write", "写库"), READ("read", "读库");
String type;
String name;
DataSourceType(String type, String name) {
this.name = name;
}
access转mysql教程视频
public String getName() {
return name;
}
public String getType() {
return type;
}
}
数据源上下⽂⼯具⽤于将数据源类型绑定到线程并指⽰AbstractRoutingDataSource进⾏数据源切换;
public class DataSourceContextHolder {
private static final ThreadLocal local = new ThreadLocal<>();
public static ThreadLocal getLocal() {
return local;
}
public static void read() {
local.set(DataSourceType.READ);
}
public static void write() {
local.set(DataSourceType.WRITE);
}
public static DataSourceType getDataSourceType() {
();
}
public static void clear() {
}
}
为了能动态切换数据源需要⼿动对Jpa进⾏配置,因此需要关闭SpringBoot的 AutoConfiguration 功能, 包括DataSource的设置,在@SpringBootApplication上进⾏排除
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class Application {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.addListeners((ContextRefreshedEvent event) -> {
if (ApplicationContext().getParent() == null) {
//spring容器启动完成
System.out.println("容器启动完成");
}
});
springApplication.run(args);
}
}
⾃定义RoutingDataSource,继承⾃AbstractRoutingDataSource
public class CustomRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
//多存在多个读或者写数据源,如read1、read2、read3;write1、write2、write3;
//可在此处可以加⼊负载均衡控制,加⼊AtomicInteger动态分配数据源
DataSourceType typeKey = DataSourceType();
return typeKey == null ? DataSourceType.READ : typeKey;
}
}
禁⽤掉 @AutoConfiguration 后需要⼿动启⽤ @EnableJpaRepositories、@EnableTransactionManagement 来初始化数据源的设置@Configuration
@EnableJpaRepositories(
basePackageClasses = {UserDao.class},
entityManagerFactoryRef = "customEntityManagerFactory",
transactionManagerRef = "customTransactionManager")
@EnableTransactionManagement
public class DynamicDataSourceConfig {
...
这⾥我们使⽤两个数据源,⼀个readDataSource、⼀个writeDataSource;在配置⽂件内通过前缀进⾏区分;
#使⽤log4jdbc 记录SQL⽇志
spring.write.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
#替换为log4jdbc的url格式
spring.write.datasource.url=jdbc:log4jdbc:mysql://192.168.2.151:3306/fake-store?
useSSL=false&useUnicode=yes&characterEncoding=UTF-8
spring.write.datasource.username=root
spring.write.datasource.password=root
useSSL=false&useUnicode=yes&characterEncoding=UTF-8
读写数据源初始化
@Bean(name = "readDataSource")
@ConfigurationProperties(prefix = "ad.datasource")
public DataSource readDataSource() {
return new DruidDataSource();;
}
@Bean(name = "writeDataSource")
@ConfigurationProperties("spring.write.datasource")
public DataSource writeDataSource() {
return new DruidDataSource();;
}
实际使⽤的数据源应由AbstractRoutingDataSource动态切换提供
@Bean(name = "dynamicDataSource")
@Primary
public DataSource dynamicDataSource() {
final CustomRoutingDataSource dynamicDataSource = new CustomRoutingDataSource();
final Map targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.READ, readDataSource());
targetDataSources.put(DataSourceType.WRITE, writeDataSource());
dynamicDataSource.setTargetDataSources(targetDataSources);
return dynamicDataSource;
}
对Jpa需要的EntityManager以及TransactionManager进⾏配置
@Autowired(required = false)
private PersistenceUnitManager persistenceUnitManager;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean customEntityManagerFactory() {
final JpaProperties jpaProperties = jpaProperties();
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
//不设置的话会产⽣异常 Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' vendorAdapter.DatabasePlatform());
vendorAdapter.setShowSql(jpaProperties.isShowSql());
vendorAdapter.Database());
vendorAdapter.setGenerateDdl(jpaProperties.isGenerateDdl());
// 使⽤dynamicDataSource
DataSource dataSource = dynamicDataSource();
//设置其他Jpa属性如hibnernate.naming-physical-strategy
Map properties = HibernateProperties(new HibernateSettings());
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(vendorAdapter, properties, persistenceUnitManager);
return builder.dataSource(dataSource).packages(IdEntity.class)
.persistenceUnit("customEntityManager").build();
}
@Bean
public PlatformTransactionManager customTransactionManager(

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。