spring+hibernate应用层读写分离
来源:互联网 发布:linux怎么建站 编辑:程序博客网 时间:2024/05/22 07:00
spring+hibernate应用层读写分离方案,是基于AbstractRoutingDataSource和AOP实现的。其中AbstractRoutingDataSource用于管理数据源并且根据key返回相应的数据源,AOP决定了什么时候使用什么数据源的key。
1、相关类的代码实现:
1)DataSource 注解类,用来标注某个方法使用的数据源,不标注则使用默认的
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface DataSource { /** * key="read" 读库(从),key="write" 写库(主) * @return */ public String key();}
2)DynamicDataSource 类重写determineCurrentLookupKey方法,返回数据源的key
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSource(); }}
3)DynamicDataSourceHolder 类用于线程安全的保存数据源的key
public class DynamicDataSourceHolder { private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<>(); public static void setDataSource(String dataSourceKey) { dataSourceHolder.set(dataSourceKey); } public static String getDataSource() { return dataSourceHolder.get(); } public static void clearDataSource() { dataSourceHolder.remove(); }}
4)DynamicDataSourceAop ,设置拦截的方法层面,下面是拦截在service层,当该service执行之前,通过判断方法有没有DataSource注解,有则根据DataSource中的key设置数据源的key;service方法执行完毕清除数据源key的设置。
service层使用DataSource注解的原则是:当service里面有写方法时就不需要设置,默认使用写库,此时读写方法都在写库中完成;当service里面没有写方法时就使用DataSource设置读库,读方法在读库中完成。
@Component@Aspect@EnableAspectJAutoProxy(proxyTargetClass = true)public class DynamicDataSourceAop { /** * service层方法执行前选择数据源 * @param point */ @Before("execution(* com.test.service..*.*(..))") public void before(JoinPoint point) { Object target = point.getTarget(); String methodName = point.getSignature().getName(); Class clazz = target.getClass(); Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes(); try { Method method = clazz.getMethod(methodName, parameterTypes); if (method != null && method.isAnnotationPresent(DataSource.class)) { DataSource data = method.getAnnotation(DataSource.class); DynamicDataSourceHolder.setDataSource(data.key()); } } catch (Exception e) { e.printStackTrace(); } } /** * service层方法执行完后清空数据源选择,当找不到相应的key的数据源会使用默认的数据源 * @param point */ @After("execution(* com.test.service..*.*(..))") public void after(JoinPoint point) { DynamicDataSourceHolder.clearDataSource(); }}
2、spring配置文件
<bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${masterconnection.url}" /> <property name="username" value="${masterconnection.username}" /> <property name="password" value="${masterconnection.password}" /> </bean> <bean id="slaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${slaveconnection.url}" /> <property name="username" value="${slaveconnection.username}" /> <property name="password" value="${slaveconnection.password}" /> </bean> <!-- 自定义动态数据源 --> <bean id="dataSource" class="com.test.dao.datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <!-- 配置读写数据源 --> <entry value-ref="masterDataSource" key="write"></entry> <entry value-ref="slaveDataSource" key="read"></entry> </map> </property> <property name="defaultTargetDataSource" ref="masterDataSource"></property> </bean> <!-- classpath是指 WEB-INF文件夹下的classes目录, classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" > <property name="dataSource" ref="dataSource"/> <property name="mappingLocations" value="classpath:com/test/dao/hbm/*.hbm.xml"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> <!-- 开启注解事务 只对当前配置文件有效 --> <tx:annotation-driven transaction-manager="txManager"/> <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
阅读全文
0 0
- spring+hibernate应用层读写分离
- 在应用层通过spring解决数据库读写分离
- 在应用层通过spring解决数据库读写分离
- 在应用层通过spring解决数据库读写分离
- 在应用层通过spring特性解决数据库读写分离
- 在应用层通过spring解决数据库读写分离
- 主题:在应用层通过spring解决数据库读写分离
- 在应用层通过spring特性解决数据库读写分离
- 在应用层通过spring特性解决数据库读写分离
- 在应用层通过spring特性解决数据库读写分离
- 在应用层通过spring特性解决数据库读写分离
- 使用Spring基于应用层实现读写分离
- Spring实现读写分离(二)--应用层实现
- mybatis 应用层读写分离
- 应用层数据库读写分离db-loadbalance
- 应用层数据库读写分离--续
- 如何在应用层通过spring特性解决数据库读写分离
- spring-hibernate-mysql实现主从读写分离
- 自定义九宫格加载的实现
- Test 4 for NOIP- Result for Day1
- mysql ERROR 1045 (28000): Access denied for user解决方法
- final与static final的区别
- mybatis中foreach标签详解
- spring+hibernate应用层读写分离
- Oracle 索引的建立、修改、删除、查询
- php 匿名函数
- MyBatis和Spring进行整合
- 创建一个不能被继承的类和只能在堆上(或栈上)创建对象
- 一张图看懂微信小程序发展
- Android studio加快编译速度
- WebService的两种方式SOAP和REST比较
- CFgym:Good morning!(dfs)