惠来做网站诈骗如何获取永久免费域名
1、简介
在Spring Boot中配置多个数据源并实现自动切换EntityManager,这里我编写了一个RoutingEntityManagerFactory和AOP(面向切面编程)的方式来实现。
这里我配置了两个数据源:primary和secondary,其中primary主数据源用来写入数据,secondary从数据源用来读取数据。
注意1: 使用Springboot3的读写分离,首先要保证主库和从库已经配置好了 数据同步,否则会导致数据不一致。
当然如果仅仅是测试的话,不同步就不影响了
注意2: SpringBoot3的JDK不能低于17
我使用的JDK版本
openjdk version "20.0.2" 2023-07-18
OpenJDK Runtime Environment (build 20.0.2+9-78)
OpenJDK 64-Bit Server VM (build 20.0.2+9-78, mixed mode, sharing)
2、数据库说明
这里我使用了本机的同一个mysql上的两个不同的数据库,在实际环境中这两个库应该是分别处于不同的服务器上,同时应该已经配置好了主从复制或主备,保证了数据的一致性,不然读写分离就没有意义了。
数据库名称 | JDBC-URL | 说明 |
---|---|---|
primary_db | jdbc:mysql://localhost:3306/primary_db | 这个是主库,设计为写入数据库 |
secondary_db | jdbc:mysql://localhost:3306/secondary_db | 这个是从库,设计为读取数据库 |
提示:虽然这里我使用的是MySQL数据库,但是在实际的开发过程中,可以替换为Postgresql或oracle等其他关系型数据库,只需要做很小的改动就可以使用了
3、准备工作
3.1、添加依赖
在你的项目里添加如下依赖
<!-- Spring Web -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- AOP -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><!-- JPA -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency><!-- MySQL -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.3.0</version>
</dependency><!-- druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.22</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
完整的pom.xml文件
下面是我在编写代码时候的完整的pom.xml文件内容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.ts</groupId><artifactId>springboot3-jpa-read-write-separation-mysql2</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot3-jpa-read-write-separation-mysql2</name><description>springBoot3 + JPA + MySQL 实现读写分离</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter AOP for @Transactional annotations --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL Database --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.3.0</version></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.22</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
3.2、准备的SQL
-- 用户表
CREATE TABLE userinfo (id int AUTO_INCREMENT PRIMARY KEY,name varchar(50),age smallint,gender varchar(3),entry_date timestamp
);-- 测试数据
INSERT INTO userinfo(name,age,gender,entry_date) VALUES
('刘峰',24,'男','2024-02-28 12:01:01'),
('舒航',25,'女','2024-02-28 12:01:01'),
('张明',26,'男','2024-02-29 12:01:01'),
('徐媛',28,'女','2024-02-29 12:01:01'),
('舒莱',29,'女','2023-07-30 12:01:01'),
('唐力',30,'男','2023-08-05 12:01:01'),
('唐莉',29,'女','2023-06-05 12:01:01'),
('王乐',27,'男','2023-07-01 12:01:01'),
('张萌',32,'女','2023-07-02 12:01:01'),
('程媛',25,'女','2023-08-02 12:01:01'),
('嫪玉',35,'女','2023-08-01 10:00:00'),
('贾茹',26,'女','2023-10-03 12:01:01'),
('胡安',25,'男','2023-11-09 12:01:01'),
('刘伟',27,'男','2023-07-09 12:01:01');
3.3、application.yml中定义多数据源配置
application.yml中定义每个数据源的连接信息。
spring:jpa:database: mysqlshow-sql: truedatasource:#主数据源 , 写入数据库primary:url: jdbc:mysql://localhost:3306/primary_db?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: root# 次数据源 , 读取数据库secondary:url: jdbc:mysql://localhost:3306/secondary_db?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: root
4、创建动态数据源
4.1、主数据源配置
package com.ts.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;/*** 主数据源配置* @author zhouq* @since 15:26 2024/03/21**/
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackages = "com.ts.service",entityManagerFactoryRef = "primaryEntityManagerFactory"
)
public class PrimaryDataSourceConfig {@Autowiredprivate JpaProperties jpaProperties;@Bean(name = "primaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {//return DataSourceBuilder.create().build();return new DruidDataSource();}//LocalContainerEntityManagerFactoryBean@Beanpublic Object primaryEntityManagerFactory(DataSource primaryDataSource,JpaProperties primaryJpaProperties) {EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(primaryJpaProperties);return builder.dataSource(primaryDataSource).packages("com.ts.model").persistenceUnit("primaryDataSource").build();}private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);}private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {// ... map JPA properties as neededreturn new HibernateJpaVendorAdapter();}}
4.2、次要数据源配置
package com.ts.config;import com.alibaba.druid.pool.DruidDataSource;
import jakarta.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;/*** 次要数据源配置* @author zhouq* @since 15:25 2024/03/21**/
@Configuration
@EnableJpaRepositories(basePackages = "com.ts.service",entityManagerFactoryRef = "secondaryEntityManagerFactory"
)
public class SecondaryDataSourceConfig {@Autowiredprivate JpaProperties jpaProperties;@Bean(name = "secondaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {//return DataSourceBuilder.create().build();return new DruidDataSource();}// LocalContainerEntityManagerFactoryBean@Beanpublic Object secondaryEntityManagerFactory(DataSource secondaryDataSource,JpaProperties secondaryJpaProperties) {EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(secondaryJpaProperties);return builder.dataSource(secondaryDataSource).packages("com.ts.model").persistenceUnit("secondaryDataSource").build();}private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);}private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {// ... map JPA properties as neededreturn new HibernateJpaVendorAdapter();}}
5、全局EntityManager配置
5.1、创建EntityManager线程工具类
EntityManagerContextHolder是一个用来保存当前线程的EntityManager名称的工具类。
package com.ts.config;/*** 用来保存当前线程的EntityManagerFactory名称 的工具类* @author zhouq* @since 14:29 2024/03/20**/
public class EntityManagerContextHolder {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public static void setEntityManagerFactoryType(String entityManagerFactoryType) {contextHolder.set(entityManagerFactoryType);}public static String getEntityManagerFactoryType() {return contextHolder.get();}public static void clearEntityManagerFactoryType() {contextHolder.remove();}
}
5.2、创建数RoutingEntityManagerFactory路由(管理多个EntityManager)
package com.ts.config;import jakarta.persistence.*;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.metamodel.Metamodel;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;import java.util.Map;/*** 动态切换EntityManagerFactory* EntityManagerFactory路由类* @author zhouq* @since 14:54 2024/03/21**/
public class RoutingEntityManagerFactory implements EntityManagerFactory{@Nullableprivate Map<String, Object> targetEntityManagerFactorys;@Nullableprivate Object defaultTargetEntityManagerFactory;@Nullablepublic Map<String, Object> getTargetEntityManagerFactorys() {return targetEntityManagerFactorys;}public void setTargetEntityManagerFactorys(@Nullable Map<String, Object> targetEntityManagerFactorys) {this.targetEntityManagerFactorys = targetEntityManagerFactorys;}@Nullablepublic Object getDefaultTargetEntityManagerFactory() {return defaultTargetEntityManagerFactory;}public void setDefaultTargetEntityManagerFactory(@Nullable Object defaultTargetEntityManagerFactory) {this.defaultTargetEntityManagerFactory = defaultTargetEntityManagerFactory;}public String determineCurrentLookupKey() {// 如果不使用读写分离,这里也可以做一个简单的负载均衡策略String entityManagerFactoryType = EntityManagerContextHolder.getEntityManagerFactoryType();//System.out.println("当前使用的数据源是:" + entityManagerFactoryType);return entityManagerFactoryType;}public EntityManagerFactory determineTargetEntityManagerFactory() {Assert.notNull(this.targetEntityManagerFactorys, "targetEntityManagerFactory router not initialized");Object lookupKey = this.determineCurrentLookupKey();EntityManagerFactory entityManagerFactory = (EntityManagerFactory)this.targetEntityManagerFactorys.get(lookupKey);if (entityManagerFactory == null && lookupKey == null) {entityManagerFactory = (EntityManagerFactory)this.defaultTargetEntityManagerFactory;}if (entityManagerFactory == null) {throw new IllegalStateException("Cannot determine target EntityManagerFactory for lookup key [" + lookupKey + "]");} else {return entityManagerFactory;}}//---------------------下面的方法都是EntityManagerFactory接口的实现------------------------------------@Overridepublic EntityManager createEntityManager() {return this.determineTargetEntityManagerFactory().createEntityManager();}@Overridepublic EntityManager createEntityManager(Map map) {return this.determineTargetEntityManagerFactory().createEntityManager(map);}@Overridepublic EntityManager createEntityManager(SynchronizationType synchronizationType) {return this.determineTargetEntityManagerFactory().createEntityManager(synchronizationType);}@Overridepublic EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {return this.determineTargetEntityManagerFactory().createEntityManager(synchronizationType,map);}@Overridepublic CriteriaBuilder getCriteriaBuilder() {return this.determineTargetEntityManagerFactory().getCriteriaBuilder();}@Overridepublic Metamodel getMetamodel() {return this.determineTargetEntityManagerFactory().getMetamodel();}@Overridepublic boolean isOpen() {return this.determineTargetEntityManagerFactory().isOpen();}@Overridepublic void close() {this.determineTargetEntityManagerFactory().close();}@Overridepublic Map<String, Object> getProperties() {return this.determineTargetEntityManagerFactory().getProperties();}@Overridepublic Cache getCache() {return this.determineTargetEntityManagerFactory().getCache();}@Overridepublic PersistenceUnitUtil getPersistenceUnitUtil() {return this.determineTargetEntityManagerFactory().getPersistenceUnitUtil();}@Overridepublic void addNamedQuery(String s, Query query) {this.determineTargetEntityManagerFactory().addNamedQuery(s,query);}@Overridepublic <T> T unwrap(Class<T> aClass) {return this.determineTargetEntityManagerFactory().unwrap(aClass);}@Overridepublic <T> void addNamedEntityGraph(String s, EntityGraph<T> entityGraph) {this.determineTargetEntityManagerFactory().addNamedEntityGraph(s,entityGraph);}
}
5.3、创建EntityManagerFactory全局配置类
package com.ts.config;import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;/*** 全局配置实体管理工厂 EntityManagerFactory* 配置EntityManagerFactory,确定使用的EntityManagerFactory* @author zhouq* @since 10:59 2024/03/21**/
@Configuration
public class EntityManagerFactoryConfig {@Autowired@Qualifier("primaryEntityManagerFactory")private Object primaryEntityManagerFactory;@Autowired@Qualifier("secondaryEntityManagerFactory")private Object secondaryEntityManagerFactory;@Beanpublic EntityManagerFactory entityManager(){String dataSourceType = EntityManagerContextHolder.getEntityManagerFactoryType();RoutingEntityManagerFactory routingEntityManagerFactory = new RoutingEntityManagerFactory();Map<String, Object> targetEntityManagerFactorys = new HashMap<String, Object>();targetEntityManagerFactorys.put("primary", primaryEntityManagerFactory); //主实体管理工厂targetEntityManagerFactorys.put("secondary", secondaryEntityManagerFactory); //次要实体管理工厂routingEntityManagerFactory.setTargetEntityManagerFactorys(targetEntityManagerFactorys);// 配置实体管理工厂routingEntityManagerFactory.setDefaultTargetEntityManagerFactory(primaryEntityManagerFactory);// 设置默认实体管理工厂return routingEntityManagerFactory;}@Beanpublic PlatformTransactionManager transactionManager() {JpaTransactionManager tm = new JpaTransactionManager();tm.setEntityManagerFactory(entityManager());return tm;}}
6、使用AOP实现EntityManager自动切换
6.1、创建AOP切面注入EntityManager类型
通过AOP在方法执行前设置EntityManagerFactory,并在方法执行后清除。
package com.ts.config;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;/*** 使用AOP注入EntityManager类型* 通过AOP在方法执行前设置EntityManager,并在方法执行后清除。* @author zhouq* @since 14:25 2024/03/20**/
@Aspect
@Component
public class EntityManagerFactoryAspect {@Before("@annotation(dataSource)")public void switchDataSource(JoinPoint point, DataSourceSwitch dataSource) {//log.info("使用的数据源是:" + dataSource.value());System.out.println("使用的数据源是:" + dataSource.value());EntityManagerContextHolder.setEntityManagerFactoryType(dataSource.value());}@After("@annotation(dataSource)")public void restoreDataSource(JoinPoint point, DataSourceSwitch dataSource) {EntityManagerContextHolder.clearEntityManagerFactoryType();}
}
6.2、创建自定义注解用于标注所使用的的
DataSourceSwitch是一个自定义注解,用来标识需要切换数据源的方法。
package com.ts.config;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解,用来标识需要切换数据源的方法* @author zhouq* @since 14:31 2024/03/20**/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSwitch {String value() default "primary";
}
7、创建实体类
package com.ts.model;import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.Accessors;
import java.util.Date;@Setter
@Getter
@Accessors(chain = true)
@AllArgsConstructor // 全参构造方法
@NoArgsConstructor // 无参构造方法
//@RequiredArgsConstructor
@ToString
@Entity
@Table(name = "userinfo")
public class Userinfo implements java.io.Serializable{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private int id;private String name;private int age;private String gender;private Date entry_date;}
8、创建Service
创建UserService接口
package com.ts.service;import com.ts.model.Userinfo;
import java.util.List;public interface UserService {/*** 获取所有* @author zhouq* @since 13:33 2024/03/20* @return java.util.List<com.ts.model.Userinfo>**/List<Userinfo> getAll();/*** 查找包含姓名的用户* @author zhouq* @since 13:34 2024/03/20* @param name 姓名* @return java.util.List<com.ts.model.Userinfo>**/List<Userinfo> queryWithName(String name);/*** 添加用户* @author zhouq* @since 13:39 2024/03/20* @return java.util.List<com.ts.model.Userinfo>**/void addUser(Userinfo userinfo);/*** 按照id删除* @author zhouq* @since 13:55 2024/03/20**/void deleteUser(int id);}
创建UserService接口实现类
package com.ts.service.impl;import com.ts.config.DataSourceSwitch;
import com.ts.model.Userinfo;
import com.ts.service.UserService;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** 基于EntityManager的实现* 这里使用 primary主数据源写入数据,secondary从数据源读取数据* @author zhouq* @since 11:08 2024/03/21**/
@Service
public class UserServiceEntityManagerImpl implements UserService {@Autowiredprivate EntityManager entityManager;/*** 获取所有用户* 这里使用 @DataSourceSwitch("secondary") 指定 读取的数据源* @author zhouq* @since 11:21 2024/03/21* @return java.util.List<com.ts.model.Userinfo>**/@Override@DataSourceSwitch("secondary")public List<Userinfo> getAll() {return entityManager.createQuery("select u from Userinfo u").getResultList();}/*** 查询用户,模糊查询* @author zhouq* @since 11:20 2024/03/21* @return java.util.List<com.ts.model.Userinfo>**/@Override@DataSourceSwitch("secondary")public List<Userinfo> queryWithName(String name) {Query query = entityManager.createQuery("select u from Userinfo u where u.name like :name");query.setParameter("name", "%" + name +"%");return query.getResultList();}/*** 添加用户* 这里使用 @DataSourceSwitch("primary") 指定写入的数据源* @author zhouq* @since 11:20 2024/03/21**/@Override@DataSourceSwitch("primary") //或者 @DataSourceSwitch@Modifying@Transactionalpublic void addUser(Userinfo userinfo) {//使用本地原生SQL查询Query nativeQuery = entityManager.createNativeQuery("insert into Userinfo(id,name,age,gender) values(:id,:name,:age,:gender)");nativeQuery.setParameter("id",userinfo.getId());nativeQuery.setParameter("name",userinfo.getName());nativeQuery.setParameter("age",userinfo.getAge());nativeQuery.setParameter("gender",userinfo.getGender());//执行查询int i = nativeQuery.executeUpdate();if ( i<= 0 ) {throw new RuntimeException("添加用户失败!");}}/*** 删除用户* 这里使用 @DataSourceSwitch("primary") 指定写入的数据源* @author zhouq* @since 11:19 2024/03/21**/@Override@DataSourceSwitch("primary") //或者 @DataSourceSwitch@Modifying@Transactionalpublic void deleteUser(int id) {//使用本地原生SQL查询Query nativeQuery = entityManager.createNativeQuery("delete from Userinfo where id = :id");nativeQuery.setParameter("id",id);//执行int i = nativeQuery.executeUpdate();if ( i<= 0 ) {throw new RuntimeException("删除用户失败!");}}}
9、编写测试类
package com.ts;import com.ts.model.Userinfo;
import com.ts.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService service;// 测试使用从库读取 查询用户@Testpublic void testGetAll() {service.getAll().forEach(System.out::println);//System.out.println(service);}// 测试使用从库读取 查询用户@Testpublic void testQuery() {service.queryWithName("张").forEach(System.out::println);}// 测试使用主库写入 添加用户@Testpublic void testAddUser() {service.addUser(new Userinfo(100,"测试用户",25,"男",new Date()));System.out.println("添加用户完成");}// 测试使用主库写入 删除用户@Testpublic void testDelete() {service.deleteUser(100);System.out.println("删除用户完成");}}
小结
关于读写分离网上的示例很多,但是都比较杂乱,而且很多的方法都是基于SpringBoot2或者SpringBoot1的,我这个是基于SpringBoot3.2.3版本实现了,
上面的代码所有的都亲自测试通过,有什么疑问可以留言评论。
几个截图:
1、查询所有
可以看到 使用的数据源是:secondary 使用的是 读 数据源
2、模糊查询
3、添加用户
看到 使用的数据源是:primary 使用的是 写 数据源
4、删除用户