diff --git a/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfig.java b/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfiguration.java similarity index 91% rename from xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfig.java rename to xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfiguration.java index d7ee2b47eddce34cbd4b5f16d982dc6bd53097d8..8cbcf973fd8bd8d9929e9dcfb72cf1c05d6df612 100644 --- a/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfig.java +++ b/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/PluginAutoConfiguration.java @@ -6,7 +6,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration -public class PluginAutoConfig { +public class PluginAutoConfiguration { @Bean public Interceptor plugin() { diff --git a/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/TransactionManagerAutoConfiguration.java b/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/TransactionManagerAutoConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..91124175c99db127a5fc182ac2aa7c039922c45d --- /dev/null +++ b/xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/config/TransactionManagerAutoConfiguration.java @@ -0,0 +1,26 @@ +package cn.bugstack.xfg.dev.tech.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.sql.DataSource; + +@Configuration +public class TransactionManagerAutoConfiguration { + + @Bean + public PlatformTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean + public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) { + TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); + transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED"); + return transactionTemplate; + } + +} diff --git a/xfg-dev-tech-app/src/main/resources/mybatis/mapper/employee_salary_mapper.xml b/xfg-dev-tech-app/src/main/resources/mybatis/mapper/employee_salary_mapper.xml index e3aff3b49b5218040fe71784ad6051251f07612c..be431f3aa8bc18e35e27dbe108b2db628f8ab4d5 100644 --- a/xfg-dev-tech-app/src/main/resources/mybatis/mapper/employee_salary_mapper.xml +++ b/xfg-dev-tech-app/src/main/resources/mybatis/mapper/employee_salary_mapper.xml @@ -13,7 +13,7 @@ - INSERT INTO employee_salary(employee, salary_total_amount, salary_merit_amount, salary_base_amount, + INSERT INTO employee_salary(employee_number, salary_total_amount, salary_merit_amount, salary_base_amount, create_time, update_time) VALUES(#{employeeNumber}, #{salaryTotalAmount}, #{salaryMeritAmount}, #{salaryBaseAmount}, now(), now()) diff --git a/xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/domain/IEmployeeServiceTest.java b/xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/domain/IEmployeeServiceTest.java index 656614478842bb89ab4d6adc0f0c17b55024c614..ecedb589e7b42cc1a41af42c558f42ef83fc849a 100644 --- a/xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/domain/IEmployeeServiceTest.java +++ b/xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/domain/IEmployeeServiceTest.java @@ -2,6 +2,7 @@ package cn.bugstack.xfg.dev.tech.test.domain; import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity; import cn.bugstack.xfg.dev.tech.domain.employee.service.IEmployeeService; +import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.junit.Test; @@ -10,6 +11,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; +import java.math.BigDecimal; @Slf4j @RunWith(SpringRunner.class) @@ -19,6 +21,19 @@ public class IEmployeeServiceTest { @Resource private IEmployeeService employeeService; + @Test + public void test_insertEmployInfo() { + EmployeeInfoEntity employeeInfo = new EmployeeInfoEntity(); + employeeInfo.setEmployeeNumber("10000022"); + employeeInfo.setEmployeeName("小卡拉米"); + employeeInfo.setEmployeeLevel("T1"); + employeeInfo.setEmployeeTitle("实习工程师"); + employeeInfo.setSalaryTotalAmount(new BigDecimal("100")); + employeeInfo.setSalaryMeritAmount(new BigDecimal("10")); + employeeInfo.setSalaryBaseAmount(new BigDecimal("90")); + employeeService.insertEmployInfo(employeeInfo); + } + @Test public void test_queryEmployInfo() { EmployeeInfoEntity employeeInfoEntity = employeeService.queryEmployInfo("10000001"); diff --git a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/model/entity/EmployeeInfoEntity.java b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/model/entity/EmployeeInfoEntity.java index 16256bc7797f989d743c55d091546db956d1755d..3ff55c216751062a73a4b0ad07f6a06c6afd77ad 100644 --- a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/model/entity/EmployeeInfoEntity.java +++ b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/model/entity/EmployeeInfoEntity.java @@ -13,6 +13,8 @@ import java.math.BigDecimal; @NoArgsConstructor public class EmployeeInfoEntity { + /** 雇员编号 */ + private String employeeNumber; /** 雇员姓名 */ private String employeeName; /** 雇员级别 */ diff --git a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/repository/IEmployeeRepository.java b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/repository/IEmployeeRepository.java index e34cd3c0c934976679e39b31d7453ad559bc7afb..23fc0d8caa4b95faaa1e50dc2d5faad81c8da7eb 100644 --- a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/repository/IEmployeeRepository.java +++ b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/repository/IEmployeeRepository.java @@ -4,6 +4,8 @@ import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity; public interface IEmployeeRepository { + void insertEmployeeInfo(EmployeeInfoEntity employeeInfoEntity); + EmployeeInfoEntity queryEmployInfo(String employNumber); } diff --git a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/EmployeeService.java b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/EmployeeService.java index 7f142f95c84799ea7b8eb11c8d35d7cd461c7cf7..941bf30118b9ead9c3528bf0994fae221e8f5885 100644 --- a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/EmployeeService.java +++ b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/EmployeeService.java @@ -12,6 +12,11 @@ public class EmployeeService implements IEmployeeService{ @Resource private IEmployeeRepository employeeRepository; + @Override + public void insertEmployInfo(EmployeeInfoEntity employeeInfoEntity) { + employeeRepository.insertEmployeeInfo(employeeInfoEntity); + } + @Override public EmployeeInfoEntity queryEmployInfo(String employNumber) { return employeeRepository.queryEmployInfo(employNumber); diff --git a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/IEmployeeService.java b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/IEmployeeService.java index 33c4815881189760f23296612ae0958ead2ebccb..6836accbffbc1540502802786d23a4c8a92d0890 100644 --- a/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/IEmployeeService.java +++ b/xfg-dev-tech-domain/src/main/java/cn/bugstack/xfg/dev/tech/domain/employee/service/IEmployeeService.java @@ -4,6 +4,8 @@ import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity; public interface IEmployeeService { + void insertEmployInfo(EmployeeInfoEntity employeeInfoEntity); + EmployeeInfoEntity queryEmployInfo(String employNumber); } diff --git a/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/EmployeeRepository.java b/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/EmployeeRepository.java index fc28cedb178a68358a7776a54474c4d64be4628a..dd4c76a08cb221533a0fb4a7f8e72a093e6c351e 100644 --- a/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/EmployeeRepository.java +++ b/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/EmployeeRepository.java @@ -7,7 +7,14 @@ import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryAdjustDAO; import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryDAO; import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO; import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; @@ -19,6 +26,40 @@ public class EmployeeRepository implements IEmployeeRepository { @Resource private IEmployeeSalaryDAO employeeSalaryDAO; + @Resource + private TransactionTemplate transactionTemplate; + + @Override + public void insertEmployeeInfo(EmployeeInfoEntity employeeInfoEntity) { + transactionTemplate.execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus status) { + try { + EmployeePO employeePO = EmployeePO.builder() + .employeeNumber(employeeInfoEntity.getEmployeeNumber()) + .employeeName(employeeInfoEntity.getEmployeeName()) + .employeeLevel(employeeInfoEntity.getEmployeeLevel()) + .employeeTitle(employeeInfoEntity.getEmployeeTitle()) + .build(); + + employeeDAO.insert(employeePO); + + EmployeeSalaryPO employeeSalaryPO = EmployeeSalaryPO.builder() + .employeeNumber(employeeInfoEntity.getEmployeeNumber()) + .salaryTotalAmount(employeeInfoEntity.getSalaryTotalAmount()) + .salaryMeritAmount(employeeInfoEntity.getSalaryMeritAmount()) + .salaryBaseAmount(employeeInfoEntity.getSalaryBaseAmount()) + .build(); + + employeeSalaryDAO.insert(employeeSalaryPO); + } catch (Exception e) { + status.setRollbackOnly(); + e.printStackTrace(); + } + } + }); + } + @Override public EmployeeInfoEntity queryEmployInfo(String employNumber) { // 查询雇员 @@ -27,6 +68,7 @@ public class EmployeeRepository implements IEmployeeRepository { EmployeeSalaryPO employeeSalaryPO = employeeSalaryDAO.queryEmployeeSalaryByEmployNumber(employNumber); return EmployeeInfoEntity.builder() + .employeeNumber(employeePO.getEmployeeNumber()) .employeeName(employeePO.getEmployeeName()) .employeeLevel(employeePO.getEmployeeLevel()) .employeeTitle(employeePO.getEmployeeTitle()) diff --git a/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/SalaryAdjustRepository.java b/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/SalaryAdjustRepository.java index fe3067828a974f416721a9d0a966a794c1323b45..0befee71e522ceb465e47be9fa47550c375cb3db 100644 --- a/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/SalaryAdjustRepository.java +++ b/xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/repository/SalaryAdjustRepository.java @@ -11,6 +11,8 @@ import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO; import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryAdjustPO; import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @@ -25,8 +27,28 @@ public class SalaryAdjustRepository implements ISalaryAdjustRepository { @Resource private IEmployeeSalaryAdjustDAO employeeSalaryAdjustDAO; + /** + * Spring Boot 事务管理的级别可以通过 `@Transactional` 注解的 `isolation` 属性进行配置。常见的事务隔离级别有以下几种: + * 1. `DEFAULT`:使用底层数据库的默认隔离级别。MySQL 默认为 `REPEATABLE READ`,Oracle 默认为 `READ COMMITTED`。 + * 2. `READ_UNCOMMITTED`:最低的隔离级别,允许读取未提交的数据变更,可能会导致脏读、不可重复读和幻读问题。 + * 3. `READ_COMMITTED`:允许读取已经提交的数据变更,可以避免脏读问题,但可能会出现不可重复读和幻读问题。 + * 4. `REPEATABLE_READ`:保证同一事务中多次读取同一数据时,结果始终一致,可以避免脏读和不可重复读问题,但可能会出现幻读问题。 + * 5. `SERIALIZABLE`:最高的隔离级别,可以避免脏读、不可重复读和幻读问题,但会影响并发性能。 + *

+ * 在 Spring Boot 中,默认的事务隔离级别为 `DEFAULT`。如果没有特殊需求,建议使用默认隔离级别。 + * SpringBoot 事务的传播行为可以通过 `@Transactional` 注解的 `propagation` 属性进行配置。常用的传播行为有以下几种: + * 1. `Propagation.REQUIRED`:默认的传播行为,如果当前存在事务,则加入该事务,否则新建一个事务; + * 2. `Propagation.SUPPORTS`:如果当前存在事务,则加入该事务,否则以非事务的方式执行; + * 3. `Propagation.MANDATORY`:如果当前存在事务,则加入该事务,否则抛出异常; + * 4. `Propagation.REQUIRES_NEW`:无论当前是否存在事务,都会新建一个事务,如果当前存在事务,则将当前事务挂起; + * 5. `Propagation.NOT_SUPPORTED`:以非事务的方式执行操作,如果当前存在事务,则将当前事务挂起; + * 6. `Propagation.NEVER`:以非事务的方式执行操作,如果当前存在事务,则抛出异常; + * 7. `Propagation.NESTED`:如果当前存在事务,则在该事务的嵌套事务中执行,否则新建一个事务。嵌套事务是独立于外部事务的,但是如果外部事务回滚,则嵌套事务也会回滚。 + *

+ * 除了传播行为,`@Transactional` 注解还可以配置其他属性,例如隔离级别、超时时间、只读等。 + */ @Override - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class, timeout = 350, propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public String adjustSalary(AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate) { String employeeNumber = adjustSalaryApplyOrderAggregate.getEmployeeNumber();