您的位置:首页 > 编程语言 > Java开发

spring+hibernate+mysql实现主从数据库动态切换

2016-04-29 15:47 761 查看
注明:项目采用spring+springMVC+hibernate框架,mysql数据库,配置采用javaConfig

本文实现的是mysql的一主一从配置,仅仅限于学习,用于项目中还需要很多处理。

版本:spring:4.2.5,springMVC:4.2.5,hibernate:5.2.4,AspectJ:1.8.9

一、配置mysql主从库

这个就不多说了,网上一搜一大堆,也不是本文的重点。


二、hibernate配置

@Configuration
@EnableTransactionManagement
@ComponentScan(value = {"com.service", "com.dao"})
@PropertySources(value = {@PropertySource("classpath:database.properties")})
public class HibernateConfig {
@Autowired
private Environment env;
@Bean
public DataSource masterDatasource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("master.jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("master.jdbc.url"));
dataSource.setUsername(env.getProperty("master.jdbc.username"));
dataSource.setPassword(env.getProperty("master.jdbc.password"));
//省去繁琐的配置
return dataSource;
}

@Bean
public DataSource slaveDatasource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("slave.jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("slave.jdbc.url"));
dataSource.setUsername(env.getProperty("slave.jdbc.username"));
dataSource.setPassword(env.getProperty("slave.jdbc.password"));
//...
return dataSource;
}

@Bean
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//默认设置为从库,因为查询需求比增删改要多;这里可以根据项目需求更改(多从或多主结构)
dynamicDataSource.setDefaultTargetDataSource(slaveDatasource());
Map<Object, Object> targetDataSources = new HashMap();
targetDataSources.put("master", masterDatasource());
//接下来设置主库,注意:master这个名字要和contextHolder的set的名字一样
dynamicDataSource.setTargetDataSources(targetDataSources);
return dynamicDataSource;
}

@Bean
public LocalSessionFactoryBean SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
//...
return sessionFactory;
}

@Bean
public PlatformTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(SessionFactory().getObject());
return transactionManager;
}

}


注明:配置好master和slave;至于slave下面的datasource这是一个总的数据源,hibernate的sessionFactory只和这个datasource关联,具体调用哪个数据源有datasource来决定。

DynamicDataSource:

public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getType();
}
}


AbstractRoutingDataSource是spring管理多数据源的一个抽象类。

DataSourceContextHolder:

public class DataSourceContextHolder {
//当前线程绑定的数据源
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void master() {
contextHolder.set("master");
}
public static String getType() {
return contextHolder.get();
}
public static void remove() {
contextHolder.remove();
}
}


三、aop切面

@Aspect
public class DynamicChangeDataSourceAop {
@Pointcut("execution(* com.dao.impl.*.save*(..)) " +
"|| execution(* com.dao.impl.*.add*(..)) " +
"|| execution(* com.dao.impl.*.update*(..)) " +
"|| execution(* com.dao.impl.*.change*(..)) " +
"|| execution(* com.dao.impl.*.delete*(..)) " +
"|| execution(* com.dao.impl.*.del*(..))")
public void masterPointCut() {
}
@Around("masterPointCut()")
public void matserDataSource(ProceedingJoinPoint joinPoint) {
try {
DataSourceContextHolder.master();
System.out.println("----切换到主库----");
joinPoint.proceed();
DataSourceContextHolder.remove();
} catch (Throwable throwable) {
throwable.printStackTrace();    //出错了
}
}
}


首先是masterPointCut方法,定义的切点为:返回值不限,com.dao.impl下所有类以save/add/update/change/delete/del开头的方法都要进入该切面,参数不限。

然后在调用proceed()之前切换到了主库。

四、配置Aop

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"com.aop"})
public class AopConfig {
@Bean
public DynamicChangeDataSourceAop dynamicChangeDataSourceAop() {
return new DynamicChangeDataSourceAop();
}
}


在spring中创建aop切面的bean。

到此就完成了主从库的动态切换了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: