Configuración de la base de datos de múltiples fuentes JPA (base de datos Dameng)


Este artículo presenta principalmente el marco SpringBoot para realizar la configuración de la base de datos de múltiples fuentes Jpa Esta vez, la base de datos nacional Dameng se utiliza como fuente de datos.

1. Preparación

Introduzca la dependencia de Spring Data Jpa en el archivo pom.xml:

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>

Agregue la configuración relevante de la base de datos en application.yml:

 spring:
   datasource:
 	  one:
 	    driver-class-name: dm.jdbc.driver.DmDriver
 	    url: jdbc:dm://127.0.0.1:5236/TESTONE
 	    username: TESTONE
 	    password: 1234567890
 	    type: com.alibaba.druid.pool.DruidDataSource
 	  two:
 	    driver-class-name: dm.jdbc.driver.DmDriver
 	    url: jdbc:dm://127.0.0.1:5237/TESTTWO
 	    username: TESTTWO
 	    password: 1234567890
 	    type: com.alibaba.druid.pool.DruidDataSource
    jpa:
      properties:
        hibernate.dialect: org.hibernate.dialect.Oracle10gDialect
        show-sql: ture
       

Escriba el archivo de configuración DataSourceConfig:

@Configuration
public class DataSourceConfig {
    
    
    @Bean
    @ConfigurationProperties("spring.datasource.one")
    @Primary
    DataSource dsOne(){
    
    
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties("spring.datasource.two")
    DataSource dsTwo(){
    
    
        return DruidDataSourceBuilder.create().build();
    }
}

2. Cree la configuración JPA

Cree dos configuraciones JPA diferentes basadas en la fuente de datos configurada. El código es el siguiente (ejemplo): La
primera configuración jpa:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.xiaoyang.dao1",//持久层路径
       entityManagerFactoryRef = "entityManagerFactoryBeanOne",
       transactionManagerRef = "platformTransactionManagerOne")
public class JpaConfigOne {
    
    

    @Resource(name = "dsOne")
    DataSource dsOne;
    @Autowired
    JpaProperties jpaProperties;

    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanOne(EntityManagerFactoryBuilder builder){
    
    
        return builder.dataSource(dsOne)
                .properties(jpaProperties.getProperties())
                .packages("org.xiaoyang.entity")//实体类路径
                .persistenceUnit("pu1")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManagerOne(EntityManagerFactoryBuilder builder){
    
    
        LocalContainerEntityManagerFactoryBean factoryOne = entityManagerFactoryBeanOne(builder);
        return new JpaTransactionManager(factoryOne.getObject());
    }
}

La segunda configuración de jpa:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "org.xiaoyang.dao2",//持久层路径
       entityManagerFactoryRef = "entityManagerFactoryBeanTwo",
       transactionManagerRef = "platformTransactionManagerTwo")
public class JpaConfigOne {
    
    

    @Resource(name = "dsTwo")
    DataSource dsTwo;
    @Autowired
    JpaProperties jpaProperties;

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBeanTwo(EntityManagerFactoryBuilder builder){
    
    
        return builder.dataSource(dsTwo)
                .properties(jpaProperties.getProperties())
                .packages("org.xiaoyang.entity")//实体类路径
                .persistenceUnit("pu1")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManagerTwo(EntityManagerFactoryBuilder builder){
    
    
        LocalContainerEntityManagerFactoryBean factoryOne = entityManagerFactoryBeanTwo(builder);
        return new JpaTransactionManager(factoryOne.getObject());
    }
}

3. Crea una clase de entidad

Cree la clase de entidad Usuario en el paquete org.xiaoyang.entity (la ruta del paquete debe ser la misma que la ruta en la clase de configuración JPA):

@Entity(name="t_user")
public class User{
    
    
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  private String name;
  private String age;
  //省略getter/setter方法
}

4. Crear repositorio

Cree el Repositorio en el paquete org.xiaoyang.dao1 y el paquete org.xiaoyang.dao2 (la ruta del paquete debe ser la misma que la ruta en la clase de configuración JPA):
El código UserDao1 es el siguiente:

public interface UserDao1 extends JpaRepository<User,Integer>{
    
    }

El código UserDao2 es el siguiente:

public interface UserDao2 extends JpaRepository<User,Integer>{
    
    }

5. Anotación + aspecto para realizar la unificación de dos fuentes de datos

Escriba una anotación para obtener la matriz del administrador de transacciones:

@Target({
    
    ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MultiDataSourceTransactional {
    
    
    /**
     * 事务管理器数组
     */
    String[] transactionManagers();
}

Escriba una clase de configuración que se dé cuenta de la unidad de dos fuentes de datos a través de anotaciones + aspectos:

/**
 * 注解+切面实现两个数据源事物统一
 */
@Component
@Aspect
public class MultiDataSourceTransactionAspect {
    
    
    /**
     * 线程本地变量:为什么使用栈?※为了达到后进先出的效果※
     */
    private static final ThreadLocal<Stack<Pair<JpaTransactionManager, TransactionStatus>>> THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 用于获取事务管理器
     */
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 事务声明
     */
    private DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    {
    
    
        // 非只读模式
        def.setReadOnly(false);
        // 事务隔离级别:采用数据库的
        def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        // 事务传播行为
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    }

    /**
     * 切面
     * 路径必须和编写获取事务管理器数组的注解路径相同
     */
    @Pointcut("@annotation(org.xiaoyang.anotations.MultiDataSourceTransactional)")
    public void pointcut() {
    
    
    }

    /**
     * 声明事务
     *
     * @param transactional 注解
     */
    @Before("pointcut() && @annotation(transactional)")
    public void before(MultiDataSourceTransactional transactional) {
    
    
        // 根据设置的事务名称按顺序声明,并放到ThreadLocal里
        String[] transactionManagerNames = transactional.transactionManagers();
        Stack<Pair<JpaTransactionManager, TransactionStatus>> pairStack = new Stack<>();
        for (String transactionManagerName : transactionManagerNames) {
    
    
            JpaTransactionManager transactionManager = applicationContext.getBean(transactionManagerName, JpaTransactionManager.class);
            TransactionStatus transactionStatus = transactionManager.getTransaction(def);
            pairStack.push(new Pair(transactionManager, transactionStatus));
        }
        THREAD_LOCAL.set(pairStack);
        System.out.println("====pairStack size========");
    }

    /**
     * 提交事务
     */
    @AfterReturning("pointcut()")
    public void afterReturning() {
    
    
        // ※栈顶弹出(后进先出)
        Stack<Pair<JpaTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
        while (!pairStack.empty()) {
    
    
            Pair<JpaTransactionManager, TransactionStatus> pair = pairStack.pop();
            pair.getKey().commit(pair.getValue());
        }
        THREAD_LOCAL.remove();
    }

    /**
     * 回滚事务
     */
    @AfterThrowing(value = "pointcut()")
    public void afterThrowing() {
    
    
        // ※栈顶弹出(后进先出)
        Stack<Pair<JpaTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
        while (!pairStack.empty()) {
    
    
            Pair<JpaTransactionManager, TransactionStatus> pair = pairStack.pop();
            pair.getKey().rollback(pair.getValue());
        }
        THREAD_LOCAL.remove();
    }

}

6. Crear servicio

Llame a la capa Dao a través del Servicio y configure la anotación para realizar la lógica empresarial: el
código de UserService es el siguiente:

public interface UserService {
    
    
    
    //两个库同时增加数据
    void addUser(User user);
    //数据库一增加数据
    void addUserOne(User user);
    //数据库二增加数据
    void addUserTwo(User user);

}

El código UserServiceImpl es el siguiente:

@Service
public class UserServiceImpl implements UserService {
    
    
   @Autowired
   private UserDao1 userDao1;
   @Autowired
   private UserDao2 userDao2;
   //同时操作两个数据库需要调用自定义注解添加事务组
   @Override
   @MultiDataSourceTransactional(transactionManagers = {
    
    "platformTransactionManagerOne","platformTransactionManagerTwo"})
   public void addUser(User user) {
    
    
        try {
    
    
            user.setName("小洋同学");
            user.setAge("23");
            userDao1.save(user);
            userDao2.save(user);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

   //单独操作数据库需要标明事务的名称
   @Override
   @Transactional("platformTransactionManagerOne")
   public void addUserOne(User user) {
    
    
        try {
    
    
            user.setName("小洋同学111");
            user.setAge("23");
            userDao1.save(user);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

   //单独操作数据库需要标明事务的名称
   @Override
   @Transactional("platformTransactionManagerTwo")
   public void addUserTwo(User user) {
    
    
        try {
    
    
            user.setName("小洋同学222");
            user.setAge("23");
            userDao2.save(user);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

}

7. Crear controlador

Utilice el controlador para llamar a la capa de servicio para implementar la función de interfaz, el código es el siguiente:

@RestController
public class UserController {
    
    

    @Autowired
    private UserService userService;
    
    @RequestMapping("/adduser")
    public void addUser() {
    
    
       User user= new User();
       userService.addUser(user);
    }
    @RequestMapping("/adduserone")
    public void addUserOne() {
    
    
       User user= new User();
       userService.addUserOne(user);
    }
    @RequestMapping("/addusertwo")
    public void addUserTwo() {
    
    
       User user= new User();
       userService.addUserTwo(user);
    }

Supongo que te gusta

Origin blog.csdn.net/qq_41534540/article/details/109403545
Recomendado
Clasificación