提交 2dfc45aa 编写于 作者: 小傅哥's avatar 小傅哥

小傅哥,feat:初始化工程,含有MyBatis操作

上级
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
/xfg-dev-tech-app/data/
/.idea/
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>xfg-dev-tech-app</module>
<module>xfg-dev-tech-domain</module>
<module>xfg-dev-tech-infrastructure</module>
<module>xfg-dev-tech-trigger</module>
<module>xfg-dev-tech-types</module>
</modules>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.28</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>xfg-dev-tech-mybatis</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 统一设定POM版本信息插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>dev</profileActive>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profileActive>prod</profileActive>
</properties>
</profile>
</profiles>
</project>
\ No newline at end of file
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>xfg-dev-tech-app</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- 自身模块 begin -->
<dependency>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-infrastructure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 自身模块 end -->
</dependencies>
<build>
<finalName>xfg-dev-tech-app</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<skipTests>true</skipTests>
<testFailureIgnore>false</testFailureIgnore>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>cn.bugstack.xfg.frame.Application</mainClass>
<layout>JAR</layout>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.dev.tech;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 启动应用
* @create 2023-07-22 08:39
*/
@SpringBootApplication
@Configurable
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class);
}
}
package cn.bugstack.xfg.dev.tech.config;
import cn.bugstack.xfg.dev.tech.plugin.FieldEncryptionAndDecryptionMybatisPlugin;
import org.apache.ibatis.plugin.Interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PluginAutoConfiguration {
@Bean
public Interceptor plugin() {
return new FieldEncryptionAndDecryptionMybatisPlugin();
}
}
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.TransactionDefinition;
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");
transactionTemplate.setTimeout(350);
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
return transactionTemplate;
}
}
package cn.bugstack.xfg.dev.tech.plugin;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.List;
import java.util.Map;
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class FieldEncryptionAndDecryptionMybatisPlugin implements Interceptor {
/**
* 密钥,必须是16位
*/
private static final String KEY = "1898794876567654";
/**
* 偏移量,必须是16位
*/
private static final String IV = "1233214566547891";
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement mappedStatement = (MappedStatement) args[0];
Object parameter = args[1];
String sqlId = mappedStatement.getId();
if (parameter != null && (sqlId.contains("insert") || sqlId.contains("update"))) {
String columnName = "employeeName";
if (parameter instanceof Map) {
List<Object> parameterList = (List<Object>) ((Map<?, ?>) parameter).get("list");
for (Object obj : parameterList) {
if (hasField(obj, columnName)) {
String fieldValue = BeanUtils.getProperty(obj, columnName);
if (StringUtils.isNoneBlank(fieldValue)) {
String encryptedValue = encrypt(fieldValue);
BeanUtils.setProperty(obj, columnName, encryptedValue);
}
}
}
} else {
if (hasField(parameter, columnName)) {
String fieldValue = BeanUtils.getProperty(parameter, columnName);
if (StringUtils.isNoneBlank(fieldValue)) {
String encryptedValue = encrypt(fieldValue);
BeanUtils.setProperty(parameter, columnName, encryptedValue);
}
}
}
}
Object result = invocation.proceed();
if (result != null && sqlId.contains("query")) {
// 查询操作,解密
String columnName = "employeeName";
if (result instanceof List) {
List<Object> resultList = (List<Object>) result;
for (Object obj : resultList) {
if (!hasField(obj, columnName)) continue;
String fieldValue = BeanUtils.getProperty(obj, columnName);
if (StringUtils.isBlank(fieldValue)) continue;
String decryptedValue = decrypt(fieldValue);
BeanUtils.setProperty(obj, columnName, decryptedValue);
}
}
}
return result;
}
public String encrypt(String content) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] raw = KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(content.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* AES解密
*
* @param content 密文
* @return 明文
* @throws Exception 异常
*/
public String decrypt(String content) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] raw = KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = Base64.getDecoder().decode(content);
byte[] original = cipher.doFinal(encrypted);
return new String(original);
}
public boolean hasField(Object obj, String fieldName) {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
return true;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
return false;
}
}
server:
port: 8090
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 80
spring:
datasource:
username: xfg-road-map
password: T&》..165Rdx2!!
url: jdbc:mysql://10.17.188.79:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
server:
port: 8090
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.jdbc.Driver
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
# 日志
logging:
level:
root: info
config: classpath:logback-spring.xml
\ No newline at end of file
spring:
config:
name: xfg-dev-tech-mybatis
profiles:
active: dev
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<springProperty scope="context" name="log.path" source="logging.path"/>
<!-- 日志格式 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>./data/log/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>./data/log/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>./data/log/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>./data/log/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文件保留天数【根据服务器预留,可自行调整】 -->
<maxHistory>7</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<!-- WARN 级别及以上 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<!-- 异步输出 -->
<appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>8192</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>true</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>false</includeCallerData>
<appender-ref ref="INFO_FILE"/>
</appender>
<appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>1024</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>true</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>false</includeCallerData>
<appender-ref ref="ERROR_FILE"/>
</appender>
<!-- 开发环境:控制台打印 -->
<springProfile name="dev">
<logger name="com.nmys.view" level="debug"/>
</springProfile>
<root level="info">
<appender-ref ref="CONSOLE"/>
<!-- 异步日志-INFO -->
<appender-ref ref="ASYNC_FILE_INFO"/>
<!-- 异步日志-ERROR -->
<appender-ref ref="ASYNC_FILE_ERROR"/>
</root>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 暂时未使用 文档:https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases -->
<typeAliases>
</typeAliases>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeDAO">
<resultMap id="employeeMap" type="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO">
<id column="id" property="id"/>
<result column="employee_number" property="employeeNumber"/>
<result column="employee_name" property="employeeName"/>
<result column="employee_level" property="employeeLevel"/>
<result column="employee_title" property="employeeTitle"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<insert id="insert" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO">
INSERT INTO employee(employee_number, employee_name, employee_level, employee_title, create_time, update_time)
VALUES(#{employeeNumber}, #{employeeName}, #{employeeLevel}, #{employeeTitle}, now(), now())
</insert>
<insert id="insertList" parameterType="java.util.List">
INSERT INTO employee(employee_number, employee_name, employee_level, employee_title, create_time, update_time)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.employeeNumber}, #{item.employeeName}, #{item.employeeLevel}, #{item.employeeTitle}, now(), now())
</foreach>
</insert>
<update id="update" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO">
UPDATE employee SET employee_level = #{employeeLevel}, employee_title = #{employeeTitle}
WHERE employee_number = #{employeeNumber}
</update>
<select id="queryEmployeeByEmployNumber" parameterType="java.lang.String" resultMap="employeeMap">
SELECT employee_number, employee_name, employee_level, employee_title
FROM employee
WHERE employee_number = #{employeeNumber}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryAdjustDAO">
<resultMap id="employeeSalaryAdjustMap" type="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryAdjustPO">
<id column="id" property="id"/>
<result column="employee_number" property="employeeNumber"/>
<result column="adjust_order_id" property="adjustOrderId"/>
<result column="adjust_total_amount" property="adjustTotalAmount"/>
<result column="adjust_base_amount" property="adjustBaseAmount"/>
<result column="adjust_merit_amount" property="adjustMeritAmount"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<insert id="insert" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryAdjustPO">
INSERT INTO employee_salary_adjust(employee_number, adjust_order_id, adjust_total_amount, adjust_base_amount, adjust_merit_amount, create_time, update_time)
VALUES(#{employeeNumber}, #{adjustOrderId}, #{adjustTotalAmount}, #{adjustBaseAmount}, #{adjustMeritAmount}, now(), now())
</insert>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryDAO">
<resultMap id="employSalaryMap" type="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO">
<id column="id" property="id"/>
<result column="employee_number" property="employeeNumber"/>
<result column="salary_total_amount" property="salaryTotalAmount"/>
<result column="salary_merit_amount" property="salaryMeritAmount"/>
<result column="salary_base_amount" property="salaryBaseAmount"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<insert id="insert" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO">
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())
</insert>
<insert id="insertList" parameterType="java.util.List">
INSERT INTO employee_salary(employee_number, salary_total_amount, salary_merit_amount, salary_base_amount,
create_time, update_time)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.employeeNumber}, #{item.salaryTotalAmount}, #{item.salaryMeritAmount}, #{item.salaryBaseAmount},
now(), now())
</foreach>
</insert>
<update id="update" parameterType="cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO">
UPDATE employee_salary SET
salary_total_amount = salary_total_amount + #{salaryTotalAmount},
salary_merit_amount = salary_merit_amount + #{salaryMeritAmount},
salary_base_amount = salary_base_amount + #{salaryBaseAmount}
WHERE employee_number = #{employeeNumber}
</update>
<select id="queryEmployeeSalaryByEmployNumber" parameterType="java.lang.String" resultMap="employSalaryMap">
SELECT employee_number, salary_total_amount, salary_merit_amount, salary_base_amount
FROM employee_salary
WHERE employee_number = #{employeeNumber}
</select>
</mapper>
package cn.bugstack.xfg.dev.tech.test;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class ApiTest {
private static final String KEY = "1234567890123456";
private static final String IV = "1234567890123456";
public static void main(String[] args) throws Exception {
System.out.println("哈喽,小卡拉米,欢迎加入小傅哥的学习阵营。https://bugstack.cn/md/road-map/road-map.html");
String encrypt = encrypt("124");
String decrypt = decrypt(encrypt);
System.out.println("加密:" + encrypt);
System.out.println("解密:" + decrypt);
}
/**
* AES加密
*
* @param content 明文
* @return 密文
* @throws Exception 异常
*/
public static String encrypt(String content) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] raw = KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(content.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* AES解密
*
* @param content 密文
* @return 明文
* @throws Exception 异常
*/
public static String decrypt(String content) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] raw = KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = Base64.getDecoder().decode(content);
byte[] original = cipher.doFinal(encrypted);
return new String(original);
}
}
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 com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
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)
@SpringBootTest
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");
log.info("测试结果:{}", JSON.toJSONString(employeeInfoEntity));
}
}
package cn.bugstack.xfg.dev.tech.test.domain;
import cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate.AdjustSalaryApplyOrderAggregate;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeEntity;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeSalaryAdjustEntity;
import cn.bugstack.xfg.dev.tech.domain.salary.model.valobj.EmployeePostVO;
import cn.bugstack.xfg.dev.tech.domain.salary.service.ISalaryAdjustApplyService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
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)
@SpringBootTest
public class ISalaryAdjustApplyServiceTest {
@Resource
private ISalaryAdjustApplyService salaryAdjustApplyService;
@Test
public void test_execSalaryAdjust() {
AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate = AdjustSalaryApplyOrderAggregate.builder()
.employeeNumber("10000001")
.orderId("100908977676002")
.employeeEntity(EmployeeEntity.builder().employeeLevel(EmployeePostVO.T3).employeeTitle(EmployeePostVO.T3).build())
.employeeSalaryAdjustEntity(EmployeeSalaryAdjustEntity.builder()
.adjustTotalAmount(new BigDecimal(100))
.adjustBaseAmount(new BigDecimal(80))
.adjustMeritAmount(new BigDecimal(20)).build())
.build();
String orderId = salaryAdjustApplyService.execSalaryAdjust(adjustSalaryApplyOrderAggregate);
log.info("调薪测试 req: {} res: {}", JSON.toJSONString(adjustSalaryApplyOrderAggregate), orderId);
}
}
package cn.bugstack.xfg.dev.tech.test.infrastructure;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeDAO;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 注意;Duplicate entry '10000010' for key 'idx_employee_number' 代表唯一索引冲突,库表中已经存在相同数据,需要修改测试数据
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class IEmployeeDAOTest {
@Resource
private IEmployeeDAO employeeDAO;
@Test
public void test_insert() {
EmployeePO employee = new EmployeePO();
employee.setEmployeeNumber("10000002");
employee.setEmployeeName("小傅哥");
employee.setEmployeeLevel("T2");
employee.setEmployeeTitle("见习工程师");
employeeDAO.insert(employee);
}
@Test
public void test_query() {
EmployeePO employeePO = employeeDAO.queryEmployeeByEmployNumber("10000002");
log.info("测试结果:{}", JSON.toJSONString(employeePO));
}
@Test
public void test_insert_list() {
List<EmployeePO> list = new ArrayList<>();
for (int i = 5; i < 8; i++) {
EmployeePO employee = new EmployeePO();
employee.setEmployeeNumber("1000001" + i);
employee.setEmployeeName("花花");
employee.setEmployeeLevel("T2");
employee.setEmployeeTitle("见习工程师");
list.add(employee);
}
employeeDAO.insertList(list);
}
}
package cn.bugstack.xfg.dev.tech.test.infrastructure;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryAdjustDAO;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryAdjustPO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
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)
@SpringBootTest
public class IEmployeeSalaryAdjustDAOTest {
@Resource
private IEmployeeSalaryAdjustDAO employeeSalaryAdjustDAO;
@Test
public void test_insert() {
EmployeeSalaryAdjustPO employeeSalaryAdjust = new EmployeeSalaryAdjustPO();
employeeSalaryAdjust.setEmployeeNumber("10000001");
employeeSalaryAdjust.setAdjustOrderId("109089990198888811");
employeeSalaryAdjust.setAdjustTotalAmount(new BigDecimal(1000));
employeeSalaryAdjust.setAdjustBaseAmount(new BigDecimal(800));
employeeSalaryAdjust.setAdjustMeritAmount(new BigDecimal(200));
employeeSalaryAdjustDAO.insert(employeeSalaryAdjust);
}
}
package cn.bugstack.xfg.dev.tech.test.infrastructure;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeSalaryDAO;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class IEmployeeSalaryDAOTest {
@Resource
private IEmployeeSalaryDAO employeeSalaryDAO;
@Test
public void test_insert() {
EmployeeSalaryPO employeeSalary = new EmployeeSalaryPO();
employeeSalary.setEmployeeNumber("10000001");
employeeSalary.setSalaryTotalAmount(new BigDecimal("5000"));
employeeSalary.setSalaryMeritAmount(new BigDecimal("1000"));
employeeSalary.setSalaryBaseAmount(new BigDecimal("4000"));
employeeSalaryDAO.insert(employeeSalary);
}
@Test
public void test_insert_list() {
List<EmployeeSalaryPO> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
EmployeeSalaryPO employeeSalary = new EmployeeSalaryPO();
employeeSalary.setEmployeeNumber("1000001" + i);
employeeSalary.setSalaryTotalAmount(new BigDecimal("5000"));
employeeSalary.setSalaryMeritAmount(new BigDecimal("1000"));
employeeSalary.setSalaryBaseAmount(new BigDecimal("4000"));
list.add(employeeSalary);
}
employeeSalaryDAO.insertList(list);
}
}
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<artifactId>xfg-dev-tech-domain</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>xfg-dev-tech-domain</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.dev.tech.domain.employee.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeInfoEntity {
/** 雇员编号 */
private String employeeNumber;
/** 雇员姓名 */
private String employeeName;
/** 雇员级别 */
private String employeeLevel;
/** 雇员岗位Title */
private String employeeTitle;
/** 薪资总额 */
private BigDecimal salaryTotalAmount;
/** 绩效工资 */
private BigDecimal salaryMeritAmount;
/** 基础工资 */
private BigDecimal salaryBaseAmount;
}
package cn.bugstack.xfg.dev.tech.domain.employee.repository;
import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity;
public interface IEmployeeRepository {
void insertEmployeeInfo(EmployeeInfoEntity employeeInfoEntity);
EmployeeInfoEntity queryEmployInfo(String employNumber);
}
package cn.bugstack.xfg.dev.tech.domain.employee.service;
import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity;
import cn.bugstack.xfg.dev.tech.domain.employee.repository.IEmployeeRepository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
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);
}
}
package cn.bugstack.xfg.dev.tech.domain.employee.service;
import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity;
public interface IEmployeeService {
void insertEmployInfo(EmployeeInfoEntity employeeInfoEntity);
EmployeeInfoEntity queryEmployInfo(String employNumber);
}
package cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeEntity;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeSalaryAdjustEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 调薪受理单聚合对象
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AdjustSalaryApplyOrderAggregate {
/** 雇员编号 */
private String employeeNumber;
/** 调薪单号 */
private String orderId;
/** 雇员实体 */
private EmployeeEntity employeeEntity;
/** 雇员实体 */
private EmployeeSalaryAdjustEntity employeeSalaryAdjustEntity;
}
package cn.bugstack.xfg.dev.tech.domain.salary.model.entity;
import cn.bugstack.xfg.dev.tech.domain.salary.model.valobj.EmployeePostVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 雇员实体对象
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeEntity {
/** 雇员级别 */
private EmployeePostVO employeeLevel;
/** 雇员岗位Title */
private EmployeePostVO employeeTitle;
}
package cn.bugstack.xfg.dev.tech.domain.salary.model.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* 调薪实体
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeSalaryAdjustEntity {
/** 总额调薪 */
private BigDecimal adjustTotalAmount;
/** 基础调薪 */
private BigDecimal adjustBaseAmount;
/** 绩效调薪 */
private BigDecimal adjustMeritAmount;
}
package cn.bugstack.xfg.dev.tech.domain.salary.model.valobj;
/**
* 雇员职位
*/
public enum EmployeePostVO {
T1("T-1", "初级工程师"),
T2("T-2", "初级工程师"),
T3("T-3", "中级工程师"),
T4("T-4", "中级工程师"),
T5("T-5", "高级工程师"),
T6("T-6", "高级工程师"),
T7("T-7", "架构师"),
T8("T-8", "架构师");
private final String code;
private final String desc;
EmployeePostVO(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
package cn.bugstack.xfg.dev.tech.domain.salary.repository;
import cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate.AdjustSalaryApplyOrderAggregate;
public interface ISalaryAdjustRepository {
String adjustSalary(AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate);
}
package cn.bugstack.xfg.dev.tech.domain.salary.service;
import cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate.AdjustSalaryApplyOrderAggregate;
public interface ISalaryAdjustApplyService {
String execSalaryAdjust(AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate);
}
package cn.bugstack.xfg.dev.tech.domain.salary.service;
import cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate.AdjustSalaryApplyOrderAggregate;
import cn.bugstack.xfg.dev.tech.domain.salary.repository.ISalaryAdjustRepository;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class SalaryAdjustApplyService implements ISalaryAdjustApplyService {
@Resource
private ISalaryAdjustRepository salaryAdjustRepository;
@Override
public String execSalaryAdjust(AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate) {
return salaryAdjustRepository.adjustSalary(adjustSalaryApplyOrderAggregate);
}
}
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<artifactId>xfg-dev-tech-infrastructure</artifactId>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 自身模块 begin -->
<dependency>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-domain</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 自身模块 end -->
</dependencies>
<build>
<finalName>xfg-dev-tech-infrastructure</finalName>
<plugins>
<!-- 编译plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.dev.tech.infrastructure.dao;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeePO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface IEmployeeDAO {
void insert(EmployeePO employee);
void insertList(List<EmployeePO> list);
void update(EmployeePO employeePO);
EmployeePO queryEmployeeByEmployNumber(String employNumber);
}
package cn.bugstack.xfg.dev.tech.infrastructure.dao;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryAdjustPO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface IEmployeeSalaryAdjustDAO {
void insert(EmployeeSalaryAdjustPO employeeSalaryAdjustPO);
}
package cn.bugstack.xfg.dev.tech.infrastructure.dao;
import cn.bugstack.xfg.dev.tech.infrastructure.po.EmployeeSalaryPO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface IEmployeeSalaryDAO {
void insert(EmployeeSalaryPO employeeSalary);
void insertList(List<EmployeeSalaryPO> list);
void update(EmployeeSalaryPO employeeSalaryPO);
EmployeeSalaryPO queryEmployeeSalaryByEmployNumber(String employNumber);
}
package cn.bugstack.xfg.dev.tech.infrastructure.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 雇员表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeePO {
/** 自增ID */
private Long id;
/** 雇员编号 */
private String employeeNumber;
/** 雇员姓名 */
private String employeeName;
/** 雇员级别 */
private String employeeLevel;
/** 雇员岗位Title */
private String employeeTitle;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
package cn.bugstack.xfg.dev.tech.infrastructure.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
/**
* 雇员薪资调整表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeSalaryAdjustPO {
/** 自增ID */
private Long id;
/** 雇员编号 */
private String employeeNumber;
/** 调薪单号 */
private String adjustOrderId;
/** 总额调薪 */
private BigDecimal adjustTotalAmount;
/** 基础调薪 */
private BigDecimal adjustBaseAmount;
/** 绩效调薪 */
private BigDecimal adjustMeritAmount;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
package cn.bugstack.xfg.dev.tech.infrastructure.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
/**
* 雇员薪资表
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeSalaryPO {
/** 自增ID */
private Long id;
/** 雇员编号 */
private String employeeNumber;
/** 薪资总额 */
private BigDecimal salaryTotalAmount;
/** 绩效工资 */
private BigDecimal salaryMeritAmount;
/** 基础工资 */
private BigDecimal salaryBaseAmount;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
package cn.bugstack.xfg.dev.tech.infrastructure.repository;
import cn.bugstack.xfg.dev.tech.domain.employee.model.entity.EmployeeInfoEntity;
import cn.bugstack.xfg.dev.tech.domain.employee.repository.IEmployeeRepository;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeDAO;
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.stereotype.Repository;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
@Repository
public class EmployeeRepository implements IEmployeeRepository {
@Resource
private IEmployeeDAO employeeDAO;
@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) {
// 查询雇员
EmployeePO employeePO = employeeDAO.queryEmployeeByEmployNumber(employNumber);
// 查询薪酬
EmployeeSalaryPO employeeSalaryPO = employeeSalaryDAO.queryEmployeeSalaryByEmployNumber(employNumber);
return EmployeeInfoEntity.builder()
.employeeNumber(employeePO.getEmployeeNumber())
.employeeName(employeePO.getEmployeeName())
.employeeLevel(employeePO.getEmployeeLevel())
.employeeTitle(employeePO.getEmployeeTitle())
.salaryTotalAmount(employeeSalaryPO.getSalaryTotalAmount())
.salaryMeritAmount(employeeSalaryPO.getSalaryTotalAmount())
.salaryBaseAmount(employeeSalaryPO.getSalaryTotalAmount())
.build();
}
}
package cn.bugstack.xfg.dev.tech.infrastructure.repository;
import cn.bugstack.xfg.dev.tech.domain.salary.model.aggreate.AdjustSalaryApplyOrderAggregate;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeEntity;
import cn.bugstack.xfg.dev.tech.domain.salary.model.entity.EmployeeSalaryAdjustEntity;
import cn.bugstack.xfg.dev.tech.domain.salary.repository.ISalaryAdjustRepository;
import cn.bugstack.xfg.dev.tech.infrastructure.dao.IEmployeeDAO;
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.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;
@Repository
public class SalaryAdjustRepository implements ISalaryAdjustRepository {
@Resource
private IEmployeeDAO employeeDAO;
@Resource
private IEmployeeSalaryDAO employeeSalaryDAO;
@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`:最高的隔离级别,可以避免脏读、不可重复读和幻读问题,但会影响并发性能。
* <p>
* 在 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`:如果当前存在事务,则在该事务的嵌套事务中执行,否则新建一个事务。嵌套事务是独立于外部事务的,但是如果外部事务回滚,则嵌套事务也会回滚。
* <p>
* 除了传播行为,`@Transactional` 注解还可以配置其他属性,例如隔离级别、超时时间、只读等。
*/
@Override
@Transactional(rollbackFor = Exception.class, timeout = 350, propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public String adjustSalary(AdjustSalaryApplyOrderAggregate adjustSalaryApplyOrderAggregate) {
String employeeNumber = adjustSalaryApplyOrderAggregate.getEmployeeNumber();
String orderId = adjustSalaryApplyOrderAggregate.getOrderId();
EmployeeEntity employeeEntity = adjustSalaryApplyOrderAggregate.getEmployeeEntity();
EmployeeSalaryAdjustEntity employeeSalaryAdjustEntity = adjustSalaryApplyOrderAggregate.getEmployeeSalaryAdjustEntity();
EmployeePO employeePO = EmployeePO.builder()
.employeeNumber(employeeNumber)
.employeeLevel(employeeEntity.getEmployeeLevel().getCode())
.employeeTitle(employeeEntity.getEmployeeTitle().getDesc()).build();
// 更新岗位
employeeDAO.update(employeePO);
EmployeeSalaryPO employeeSalaryPO = EmployeeSalaryPO.builder()
.employeeNumber(employeeNumber)
.salaryTotalAmount(employeeSalaryAdjustEntity.getAdjustTotalAmount())
.salaryMeritAmount(employeeSalaryAdjustEntity.getAdjustMeritAmount())
.salaryBaseAmount(employeeSalaryAdjustEntity.getAdjustBaseAmount())
.build();
// 更新薪酬
employeeSalaryDAO.update(employeeSalaryPO);
EmployeeSalaryAdjustPO employeeSalaryAdjustPO = EmployeeSalaryAdjustPO.builder()
.employeeNumber(employeeNumber)
.adjustOrderId(orderId)
.adjustTotalAmount(employeeSalaryAdjustEntity.getAdjustTotalAmount())
.adjustBaseAmount(employeeSalaryAdjustEntity.getAdjustMeritAmount())
.adjustMeritAmount(employeeSalaryAdjustEntity.getAdjustBaseAmount())
.build();
// 写入流水
employeeSalaryAdjustDAO.insert(employeeSalaryAdjustPO);
return orderId;
}
}
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<artifactId>xfg-dev-tech-trigger</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- 自身模块 begin -->
<dependency>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-domain</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-types</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 自身模块 end -->
</dependencies>
<build>
<finalName>xfg-frame-trigger</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.dev.tech.trigger.http;
import cn.bugstack.xfg.frame.types.Constants;
import cn.bugstack.xfg.frame.types.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@RestController
public class Controller {
@Resource
private ThreadPoolExecutor threadPoolExecutor;
/**
* http://localhost:8090/success
*/
@RequestMapping("/success")
public Response<String> success() {
log.info("测试调用");
try {
// 随机休眠
Thread.sleep(new Random().nextInt(1000));
// 开启线程
threadPoolExecutor.execute(() -> {
log.info("开启线程");
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (new Random().nextInt(100) == 1) throw new RuntimeException("异常");
return Response.<String>builder()
.code(Constants.ResponseCode.SUCCESS.getCode())
.info(Constants.ResponseCode.SUCCESS.getInfo())
.data("查询用户信息,小傅哥")
.build();
}
}
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.bugstack</groupId>
<artifactId>xfg-dev-tech-rocketmq</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<artifactId>xfg-dev-tech-types</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
</dependencies>
<build>
<finalName>xfg-frame-types</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.bugstack.xfg.frame.types;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
public class Constants {
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum ResponseCode {
SUCCESS("0000", "成功"),
UN_ERROR("0001", "未知失败"),
ILLEGAL_PARAMETER("0002", "非法参数"),
INDEX_DUP("0003", "主键冲突"),
RATE_LIMITER("0004", "请求已被限流,超过限流配置");
private String code;
private String info;
}
/**
* 全局属性
*/
public static final class Global {
/**
* 空节点值
*/
public static final Long TREE_NULL_NODE = 0L;
}
/**
* 决策树节点
*/
public static final class NodeType {
/**
* 树茎
*/
public static final Integer STEM = 1;
/**
* 果实
*/
public static final Integer FRUIT = 2;
}
/**
* 规则限定类型
*/
public static final class RuleLimitType {
/**
* 等于
*/
public static final int EQUAL = 1;
/**
* 大于
*/
public static final int GT = 2;
/**
* 小于
*/
public static final int LT = 3;
/**
* 大于&等于
*/
public static final int GE = 4;
/**
* 小于&等于
*/
public static final int LE = 5;
/**
* 枚举
*/
public static final int ENUM = 6;
}
}
package cn.bugstack.xfg.frame.types;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Response<T> implements Serializable {
private String code;
private String info;
private T data;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册