栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多数据源模拟分布式事务之SpringBoot+Jta-Atomikos+Jpa

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多数据源模拟分布式事务之SpringBoot+Jta-Atomikos+Jpa

0.实体类
package com.example.jta.entity.db1;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "goods")
@Data
public class Goods {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    private String name;

}
package com.example.jta.entity.db2;

import lombok.Data;
import lombok.ToString;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name = "user")
@Data
@ToString
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    @Column
    private String username;

    @Column
    private Date birthday;

    @Column
    private String sex;

    @Column
    private String address;

}
布局图

 

1.引入依赖


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.6.RELEASE
         
    
    com.example
    jta-atomikos
    0.0.1-SNAPSHOT
    jta-atomikos
    Demo project for Spring Boot
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-jta-atomikos
        

        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
            mysql
            mysql-connector-java
            
            8.0.11
        

        
            com.alibaba
            druid
            1.1.12
        

        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


2.Yaml配置
spring:
  datasource:
    db1:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/db1?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
      username: root
      password: root
    db2:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/db2?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
      username: root
      password: root
  jpa:
    database: mysql
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL57Dialect
    #对于多数据源必须要这样设置,否则会报错
    properties:
      hibernate.hbm2ddl.auto: update
server:
  port: 10010
3.数据源配置
package com.example.jta.config;

import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import org.springframework.beans.factory.annotation.Value;
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.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Objects;


@Configuration
@EnableJpaRepositories(basePackages = {"com.example.jta.dao.db1"}, entityManagerFactoryRef = "goodsEntityManagerFactory", transactionManagerRef = "goodsTransactionManager")
public class GoodsDataSourceConfig {

    @Resource
    private JpaProperties jpaProperties;

    @Value("${spring.datasource.db1.jdbc-url}")
    private String jdbcUrl;

    @Value("${spring.datasource.db1.username}")
    private String username;

    @Value("${spring.datasource.db1.password}")
    private String password;

    
    @Primary
    @Bean(name = "goodsDataSource")
    public DataSource goodsDataSource() {
        DruidXADataSource druidXADataSource = new DruidXADataSource();
        druidXADataSource.setUrl(jdbcUrl);
        druidXADataSource.setUsername(username);
        druidXADataSource.setPassword(password);
        druidXADataSource.setDefaultAutoCommit(false);
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(druidXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("goodsDataSource");
        atomikosDataSourceBean.setPoolSize(5);

        return atomikosDataSourceBean;
    }

    
    @Primary
    @Bean(name = "goodsEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean goodsEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(goodsDataSource())
                .properties(jpaProperties.getProperties())
                //设置实体类所在位置:类或包
                .packages("com.example.jta.entity.db1")
                //持久化单元名称
                .persistenceUnit("goodsPersistenceUnit")
                .build();
    }

    
    @Primary
    @Bean(name = "goodsTransactionManager")
    public PlatformTransactionManager goodsTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(Objects.requireNonNull(goodsEntityManagerFactory(builder).getObject()));
    }

}
package com.example.jta.config;

import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import org.springframework.beans.factory.annotation.Value;
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.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Objects;


@Configuration
@EnableJpaRepositories(basePackages = {"com.example.jta.dao.db2"},entityManagerFactoryRef = "userEntityManagerFactory",transactionManagerRef = "userTransactionManager")
public class UserDataSourceConfig {

    
    @Resource
    private JpaProperties jpaProperties;

    @Value("${spring.datasource.db2.jdbc-url}")
    private String jdbcUrl;

    @Value("${spring.datasource.db2.username}")
    private String username;

    @Value("${spring.datasource.db2.password}")
    private String password;

    @Bean(name = "userDataSource")
    public DataSource userDataSource() {
        DruidXADataSource druidXADataSource = new DruidXADataSource();
        druidXADataSource.setUrl(jdbcUrl);
        druidXADataSource.setUsername(username);
        druidXADataSource.setPassword(password);
        druidXADataSource.setDefaultAutoCommit(false);

        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(druidXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("userDataSource");
        atomikosDataSourceBean.setPoolSize(5);

        return atomikosDataSourceBean;
    }

    
    @Bean(name = "userEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory(EntityManagerFactoryBuilder builder){
      return builder.dataSource(userDataSource())
              .properties(jpaProperties.getProperties())
              //设置实体类所在位置:类或包
              .packages("com.example.jta.entity.db2")
              //持久化单元名称
              .persistenceUnit("userPersistenceUnit")
              .build();
    }

    
    @Bean(name = "userTransactionManager")
    public PlatformTransactionManager userTransactionManager(EntityManagerFactoryBuilder builder){
        return new JpaTransactionManager(Objects.requireNonNull(userEntityManagerFactory(builder).getObject()));
    }

}
package com.example.jta.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.UserTransaction;


@Configuration
public class JtaTransactionManagerConfig {

    @Primary
    @Bean(name = "jtaTransactionManager")
    public JtaTransactionManager regTransactionManager () {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        UserTransaction userTransaction = new UserTransactionImp();
        return new JtaTransactionManager(userTransaction, userTransactionManager);
    }

}
4.控制层Controller
package com.example.jta.controller;

import com.example.jta.entity.db1.Goods;
import com.example.jta.entity.db2.User;
import com.example.jta.service.GoodsService;
import com.example.jta.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
public class TransactionController {

    @Autowired
    private UserService userService;

    @Autowired
    private GoodsService goodsService;

    @Transactional(value = "jtaTransactionManager", rollbackFor = Exception.class)
    @GetMapping("/add")
    public ResponseEntity addTest() {
        Goods goods = new Goods();
        goods.setId(1L);
        goods.setName("涡轮发动机");
        goodsService.addGoods(goods);

        User user = new User();
        user.setSex("男");
        user.setUsername("周杰伦");
        user.setAddress("上海");
        user.setBirthday(new Date());
        userService.addUser(user);

        return ResponseEntity.ok("添加成功");
    }

    //在该接口中故意制造一个除零异常
    @Transactional(value = "jtaTransactionManager", rollbackFor = Exception.class)
    @GetMapping("/add2")
    public ResponseEntity addTest2() {
        Goods goods = new Goods();
        goods.setId(2L);
        goods.setName("兰博基尼");
        goodsService.addGoods(goods);

        User user = new User();
        user.setSex("男");
        user.setUsername("周润发");
        user.setAddress("上海");
        user.setBirthday(new Date());
        userService.addUser(user);

        int i = 10 / 0;

        return ResponseEntity.ok("添加成功");
    }

}
5.业务层Service
package com.example.jta.service;

import com.example.jta.entity.db1.Goods;

import java.util.List;

public interface GoodsService {

    List findAll();

    Goods addGoods(Goods goods);

}
package com.example.jta.service;

import com.example.jta.entity.db2.User;

import java.util.List;

public interface UserService {

    List findAll();

    User addUser(User user);

}
package com.example.jta.service.impl;

import com.example.jta.dao.db1.GoodsRepository;
import com.example.jta.entity.db1.Goods;
import com.example.jta.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

@Service
@Transactional(transactionManager = "goodsTransactionManager",rollbackFor = Exception.class,propagation = Propagation.NEVER)
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private GoodsRepository goodsRepository;

    @Override
    public List findAll() {
        return goodsRepository.findAll();
    }

    @Override
    public Goods addGoods(Goods goods) {
        try {
            return goodsRepository.save(goods);
        }catch (Exception e){
            //强制手动事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
        }
        return null;
    }

}
package com.example.jta.service.impl;

import com.example.jta.dao.db2.UserRepository;
import com.example.jta.entity.db2.User;
import com.example.jta.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

@Service
@Transactional(transactionManager = "userTransactionManager", rollbackFor = Exception.class, propagation = Propagation.NEVER)
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public List findAll() {
        return userRepository.findAll();
    }

    @Override
    public User addUser(User user) {
        try {
            return userRepository.save(user);
        } catch (Exception e) {
            //强制手动事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
        }
        return null;
    }
}
6.数据层Dao
package com.example.jta.dao.db1;

import com.example.jta.entity.db1.Goods;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface GoodsRepository extends JpaRepository, JpaSpecificationExecutor {
}
package com.example.jta.dao.db2;

import com.example.jta.entity.db2.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository, JpaSpecificationExecutor {
}
7.启动类
package com.example.jta;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
//手动进行事务管理
@EnableTransactionManagement
public class JtaAtomikosApplication {

    public static void main(String[] args) {
        SpringApplication.run(JtaAtomikosApplication.class, args);
    }

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/336432.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号