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配置
注明:配置好master和slave;至于slave下面的datasource这是一个总的数据源,hibernate的sessionFactory只和这个datasource关联,具体调用哪个数据源有datasource来决定。
DynamicDataSource:
AbstractRoutingDataSource是spring管理多数据源的一个抽象类。
DataSourceContextHolder:
三、aop切面
首先是masterPointCut方法,定义的切点为:返回值不限,com.dao.impl下所有类以save/add/update/change/delete/del开头的方法都要进入该切面,参数不限。
然后在调用proceed()之前切换到了主库。
四、配置Aop
在spring中创建aop切面的bean。
到此就完成了主从库的动态切换了。
本文实现的是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。
到此就完成了主从库的动态切换了。
相关文章推荐
- Java虚拟机内存分布总结
- java利用poi包 为excel生成超链接
- Java多线程之synchronized和volatile
- Java多线程学习(吐血超详细总结)
- 关于java构造器初始化顺序例子
- Dwr3.0纯注解(纯Java Code配置)配置与应用浅析一之零配置文件化
- java集合迭代器Iterator中的remove陷阱
- Java多线程之synchronized和volatile
- eclipse中ant的安装
- Spring 配置JNDI(连接池)
- Java中Vector和ArrayList的区别
- Eclipse常用的快捷键
- Java字符串的10大热点问题盘点
- java基础笔记03
- java常用工具库
- 深入理解Java:String
- eclipse 全局搜索
- 【排序算法】基数排序(java实现)
- java 连接数据库
- Java 8 Optional类深度解析