`
weihong01267
  • 浏览: 51656 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

转 spring jpa 读写分离

    博客分类:
  • java
 
阅读更多

pring jpa 读写分离

博客分类:
 

本文主要解决基于spring data jpa读写分离。

思想:在dataSource做路由,根据事务判断使用主从数据源。

背景:spring+spring data jpa(hibernate jpa)

首先是jpa配置,时间有限在原基础上该的,既有java配置也有xml配置,见谅。

先声明EntityManager

 

 

Xml代码  收藏代码
  1. <!-- Jpa Entity Manager 配置 -->  
  2.     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">   
  3.         <property name="dataSource" ref="dataSource"/>  
  4.         <property name="jpaVendorAdapter">  
  5.             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">  
  6.                 <property name="showSql" value="false" />  
  7.                 <property name="generateDdl" value="true" />  
  8.                 <property name="database" value="MYSQL" />  
  9.             </bean>  
  10.         </property>  
  11.         <property name="packagesToScan" value="com.lee"/>  
  12.         <property name="jpaProperties">  
  13.             <props>  
  14.                 <!-- 命名规则 My_NAME->MyName -->  
  15.                 <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>  
  16.             </props>  
  17.         </property>  
  18.     </bean>  
  19.       
  20.     <!-- 动态dataSource -->  
  21.     <bean id="dataSource" class="com.lee.spring.core.jpa.rws.RwDataSource">  
  22.         <property name="targetDataSources">    
  23.               <map key-type="java.lang.String">    
  24.                   <!-- write -->  
  25.                  <entry key="master" value-ref="masterDataSource"/>    
  26.                  <!-- read -->  
  27.                  <entry key="slave" value-ref="slaveDataSource"/>    
  28.               </map>    
  29.         </property>    
  30.         <property name="defaultTargetDataSource" ref="masterDataSource"/>    
  31.     </bean>  
  32.       
  33.     <!-- 主(写)数据源 -->  
  34.     <bean id="masterDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
  35.         <property name="driverClass" value="${jdbc.master.driver}" />  
  36.         <property name="jdbcUrl" value="${jdbc.master.url}" />  
  37.         <property name="user" value="${jdbc.master.username}" />  
  38.         <property name="password" value="${jdbc.master.password}" />  
  39.         <property name="maxPoolSize" value="30" />  
  40.         <property name="minPoolSize" value="10" />  
  41.         <property name="initialPoolSize" value="1" />  
  42.         <property name="maxIdleTime" value="0" />  
  43.         <property name="acquireIncrement" value="3" />  
  44.         <property name="acquireRetryAttempts" value="30" />  
  45.         <property name="checkoutTimeout" value="0" />  
  46.         <property name="idleConnectionTestPeriod" value="60" />  
  47.     </bean>  
  48.       
  49.     <!-- 从(读)数据源 -->  
  50.     <bean id="slaveDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  
  51.         <property name="driverClass" value="${jdbc.slave.driver}" />  
  52.         <property name="jdbcUrl" value="${jdbc.slave.url}" />  
  53.         <property name="user" value="${jdbc.slave.username}" />  
  54.         <property name="password" value="${jdbc.slave.password}" />  
  55.         <property name="maxPoolSize" value="30" />  
  56.         <property name="minPoolSize" value="10" />  
  57.         <property name="initialPoolSize" value="1" />  
  58.         <property name="maxIdleTime" value="0" />  
  59.         <property name="acquireIncrement" value="3" />  
  60.         <property name="acquireRetryAttempts" value="30" />  
  61.         <property name="checkoutTimeout" value="0" />  
  62.         <property name="idleConnectionTestPeriod" value="60" />  
  63.     </bean>  

 用java声明的jpa设置

 

 

Java代码  收藏代码
  1. import javax.annotation.Resource;  
  2. import javax.persistence.EntityManagerFactory;  
  3.   
  4. import org.slf4j.Logger;  
  5. import org.slf4j.LoggerFactory;  
  6. import org.springframework.context.annotation.Bean;  
  7. import org.springframework.context.annotation.Configuration;  
  8. import org.springframework.context.annotation.PropertySource;  
  9. import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;  
  10. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;  
  11. import org.springframework.transaction.annotation.EnableTransactionManagement;  
  12.   
  13. import com.lee.spring.core.jpa.rws.MyJpaTransactionManager;  
  14.   
  15. /** 
  16.  * spring-jpa设置 
  17.  * @author lee 
  18.  * 
  19.  */  
  20. @Configuration  
  21. @PropertySource("classpath:/application.properties")  
  22. @EnableTransactionManagement  
  23. @EnableJpaRepositories(basePackages = {"com.lee.**.dao"})  
  24. public class SpringDaoConfig {  
  25.     private static final Logger logger = LoggerFactory.getLogger(SpringDaoConfig.class);  
  26.     @Resource(name="entityManagerFactory")  
  27.     private EntityManagerFactory entityManagerFactory;    
  28.       
  29.     /** 
  30.      * 描述 : 负责解析资源文件 
  31.      * 这个类必须有,而且必须声明为static,否则不能正常解析 
  32.      * @return 
  33.      */  
  34.     @Bean    
  35.     public static PropertySourcesPlaceholderConfigurer placehodlerConfigurer() {    
  36.         logger.info("PropertySourcesPlaceholderConfigurer");    
  37.         return new PropertySourcesPlaceholderConfigurer();    
  38.     }    
  39.       
  40.     @Bean(name="entityManagerFactory")  
  41.     public EntityManagerFactory entityManagerFactory() {  
  42.         return entityManagerFactory;  
  43.     }   
  44.     
  45.     @Bean(name="transactionManager")  
  46.     public MyJpaTransactionManager transactionManager() {  
  47.         MyJpaTransactionManager transactionManager = new MyJpaTransactionManager();  
  48.         transactionManager.setEntityManagerFactory(entityManagerFactory);  
  49.         return transactionManager;  
  50.     }  
  51.       
  52. }  

 

 

由上可以看出跟平常不同的有两点

  1. 自定义动态连接池RwDataSource
  2. 自定义事务管理器MyJpaTransactionManager

其中MyJpaTransactionManager主要作用在于判断事务类别。因为我是使用注解@Transactional来声明事务,所以该类做了如下调整

 

Java代码  收藏代码
  1. import org.slf4j.Logger;  
  2. import org.slf4j.LoggerFactory;  
  3. import org.springframework.orm.jpa.JpaTransactionManager;  
  4. import org.springframework.transaction.TransactionDefinition;  
  5. import org.springframework.transaction.support.DefaultTransactionStatus;  
  6.   
  7. @SuppressWarnings("serial")  
  8. public class MyJpaTransactionManager extends JpaTransactionManager{  
  9.     private static final Logger logger = LoggerFactory.getLogger(MyJpaTransactionManager.class);  
  10.     @Override  
  11.     protected void doBegin(Object transaction, TransactionDefinition definition) {  
  12.         if(definition.isReadOnly()){  
  13.             RwDataSourceHolder.localSlave();  
  14.         }else{  
  15.             RwDataSourceHolder.localMaster();  
  16.         }  
  17.         logger.info("jpa-transaction:begin-----now dataSource is ["+RwDataSourceHolder.getDataSouce()+"]");  
  18.         super.doBegin(transaction, definition);  
  19.     }  
  20.     @Override  
  21.     protected void doCommit(DefaultTransactionStatus status) {  
  22.         logger.info("jpa-transaction:commit-----now dataSource is ["+RwDataSourceHolder.getDataSouce()+"]");  
  23.         super.doCommit(status);  
  24.     }  
  25. }  

 

 

上面涉及到definition.isReadOnly()来判断我的注解声明,依此来决定使用哪个dataSource。

Java代码  收藏代码
  1. public class RwDataSourceHolder {  
  2.     public static final String MASTER = "master";   //主(写)连接池  
  3.     public static final String SLAVE = "slave";     //从(读)连接池  
  4.       
  5.     public static final ThreadLocal<String> holder = new ThreadLocal<String>();  
  6.   
  7.     public static void localMaster() {  
  8.         holder.set(MASTER);  
  9.     }  
  10.       
  11.     public static void localSlave() {  
  12.         holder.set(SLAVE);  
  13.     }  
  14.   
  15.     public static String getDataSouce() {  
  16.         return holder.get();  
  17.     }  
  18. }  

 最后是RwDataSource,这个完全基于spring提供的AbstractRoutingDataSource

Java代码  收藏代码
  1. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;  
  2.   
  3. public class RwDataSource extends AbstractRoutingDataSource {  
  4.   
  5.     @Override  
  6.     protected Object determineCurrentLookupKey() {  
  7.         return RwDataSourceHolder.getDataSouce();  
  8.     }  
  9.   
  10. }  

 

分享到:
评论

相关推荐

    SpringBoot2.x 继承 AbstractRoutingDataSource 动态数据源切换实现 JPA读写分离

    SpringBoot2.x 继承 AbstractRoutingDataSource 动态数据源切换实现 JPA读写分离。 使用MyCat代理MySQL8数据库,添加root账户(读写)和user账户(只读)模拟读写简单分离。

    SpringBoot集成Spring Data JPA及读写分离

    SpringBoot集成Spring Data JPA及读写分离是现代Java Web应用程序中常见的技术组合,用于高效地管理和处理数据库操作。Spring Boot简化了应用的初始化和配置,而Spring Data JPA则进一步降低了使用Java Persistence ...

    整合Spring Data JPA1

    - **多数据源支持**:可以方便地配置和管理多个数据源,实现数据隔离和读写分离。 **2. Spring Boot 整合 Spring Data JPA** - **环境搭建**:在 Maven 项目中添加相关依赖,包括 `spring-boot-starter-data-jpa`...

    springboot 实现mysql读写分离

    在SpringBoot中实现MySQL的读写分离,我们需要依赖于Spring Data JPA或MyBatis等持久层框架,并结合配置中心(如Apache ZooKeeper或Consul)来动态管理读写数据库的地址。以下是具体步骤: 1. **设置主从复制**:在...

    Spring Boot使用spring-data-jpa配置Mysql多数据源

    在Spring Boot应用中,使用`spring-data-jpa`来配置MySQL多数据源是一项常见的需求,尤其是在构建大型分布式系统时,为了实现数据隔离、负载均衡或读写分离等目的。本教程将详细介绍如何在Spring Boot项目中配置多个...

    spring-boot-mybatis多数据源读写分离实例

    本实例将探讨如何利用Spring Boot和MyBatis框架实现多数据源的读写分离。以下是关于这个主题的详细讲解。 1. **Spring Boot**:Spring Boot是由Pivotal团队提供的全新框架,旨在简化Spring应用的初始搭建以及开发...

    springMVC读写分离

    - 使用如MyBatis或JPA等持久层框架时,需要确保在执行SQL时,根据读写分离规则选择合适的数据源。例如,在MyBatis中,可以通过`@Transactional`注解和自定义拦截器实现。 6. **监控与故障转移** - 实现监控机制,...

    数据库读写分离(aop方式完整实现)

    最近项目要支持读写分离, 网上找了很多,但都是不太完整,我自己整理了下供大家参考。 我的项目使用的框架: springMvc+spring+hibernate+springJPA+maven, 数据库连接池用阿里的druid。

    spring的自动获取数据源,实现读写分离

    在Spring框架中,数据源的自动获取和读写分离是两个关键的概念,它们对于构建高效、可扩展的数据库应用至关重要。下面将详细讲解这两个概念及其实施方法。 首先,"spring的自动获取数据源"通常指的是Spring框架中的...

    Mysql主从集群搭建方法,以及基于spring boot注解式数据库读写分离代码示例.zip

    使用Spring Boot的`JdbcTemplate`或者`JPA`(Java Persistence API)进行数据库操作时,可以透明地处理读写分离。只需配置好数据源,框架会自动根据规则选择合适的数据源。 6. **监控和故障转移**: 为了保证高...

    基于Springboot结合aop实现读写分离实例工程系统-源码

    这个项目为学习和实践数据库读写分离提供了一个很好的起点,开发者可以从中学习到如何在Spring Boot环境下,利用AOP进行业务逻辑的拦截和定制,从而实现高效的数据库访问策略。同时,对于想要提升系统性能和扩展性的...

    Spring AOP + SpringMVC +Mybatis做动态数据源,实现读写分离

    Spring AOP + SpringMVC +Mybatis做动态数据源,实现读写分离Spring AOP + SpringMVC +Mybatis做动态数据源,实现读写分离Spring AOP + SpringMVC +Mybatis做动态数据源,实现读写分离

    SpringBoot+MybatisPlus多数据源配置,主从库读写分离完整例子

    在现代企业级应用开发中,数据管理是至关重要的部分,特别是在高并发、大数据量的场景下,为了提高系统的性能和稳定性,通常会采用读写分离和多数据源的策略。本篇文章将详细讲解如何在SpringBoot项目中结合...

    动态数据源 读写分离

    总结起来,动态数据源和读写分离是通过自定义注解和Spring AOP来实现的,这种方法提高了代码的可维护性和灵活性,同时降低了数据库的压力。结合Spring Data,我们可以构建出高效、可扩展的数据库访问层,满足大规模...

    Spring MVC + JPA + MQ + redis +activemq 集成项目实例

    在本项目实例中,我们探讨的是一个基于Spring MVC、JPA、消息队列MQ以及缓存技术redis和ActiveMQ的集成应用。这个实例涵盖了多种关键的技术栈,旨在提供一个全面的解决方案,帮助开发者构建高效、可扩展的后端系统。...

    springboot 学习mybatis+mysql读写分离(一写多读)+事务.zip

    在IT行业中,数据库的读写分离是提升系统性能和可扩展性的重要技术手段,尤其是在高并发的场景下。本教程将带你深入理解如何在SpringBoot项目中结合Mybatis和MySQL实现读写分离,并且探讨事务管理。以下是相关知识点...

    springboot+shardingjdbc+hikari+jpa+KingbaseES V8R6

    1:多租户系统集成 2:集成shardingjdbc分库分表 3:集成shardingjdbc读写分离 4:集成人大金仓数据库 5:重写了JPA-saveandflush方法 6:修复了JPA更新数据为null的问题 7:解压后导入idea,创建数据库即可运行测试

    使用sharding-jdbc实现读写分离和分库分表.zip

    在IT行业中,数据库管理是关键任务之一,尤其是在大型系统中,如何有效地进行读写分离和分库分表显得尤为重要。本教程将通过介绍如何使用Sharding-JDBC在SpringBoot框架下实现这一目标,来帮助你优化数据库性能和...

    Use the spring to separate read and write

    标题中的“Use the spring to separate read and write”指的是在Java开发中,利用Spring框架来实现数据库的读写分离。在大型应用中,为了提高数据库的性能和可用性,通常会采用主从复制的方式,将读操作和写操作...

    使用springboot + JPA / MyBatis 实现多数据源动态切换

    在现代企业级应用开发中,数据源的动态切换是一个重要的需求,特别是在分布式系统中,可能需要连接多个数据库来实现读写分离、数据分区等策略。本教程将详细讲解如何使用Spring Boot结合JPA或MyBatis框架实现多数据...

Global site tag (gtag.js) - Google Analytics