相关信息
对于数据库表的增删改查,这里封装了通用的抽象类,方便后续业务开发,这里,主要封装了通用的增删改查方法,以及通用的分页查询方法
数据库表实体类
BaseEntity
基础实体类,包含主键、创建时间、更新时间、创建人、更新人五个基础字段,以及一个非数据库扩展字段expansion
用于扩展数据传输等
相关信息
对于数据库表的增删改查,这里封装了通用的抽象类,方便后续业务开发,这里,主要封装了通用的增删改查方法,以及通用的分页查询方法
基础实体类,包含主键、创建时间、更新时间、创建人、更新人五个基础字段,以及一个非数据库扩展字段expansion
用于扩展数据传输等
可以在需要启动运行的模块里面添加这个依赖
<!--启动模块-->
<dependency>
<groupId>io.github.mangocrisp</groupId>
<artifactId>spring-taybct-tool-launch</artifactId>
</dependency>
基于 SpringBoot 3.2.5 开发的 Java 后端后台管理业务基础框架,常用的业务功能已经集成,开箱即用,相关使用说明,可以参考:
${_database_id_}
来得到连接的数据库类型,用以替代 ${_databaseId}
(单数据源的情况下还是可以正常使用 ${_databaseId})io.github.mangocrisp.spring.taybct.tool.core.ds.sync
,目前实现了PGSQL
ORACLE
MySQL
三库之前的库对库流式同步,并且提供了 IDataSyncHandler
接口用于扩展,你还可以同步其他类型的数据库,只需要实现 IDataSyncHandler
接口即可import io.github.mangocrisp.spring.taybct.tool.core.ds.sync.DataSyncConfig;
import io.github.mangocrisp.spring.taybct.tool.core.ds.sync.DataSyncService;
import io.github.mangocrisp.spring.taybct.tool.core.ds.sync.DriverType;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* <pre>
* 同步数据测试(流式)
* </pre>
*
* @author XiJieYin
* @since 2025/4/15 11:35
*/
@SpringBootTest
@Slf4j
public class SyncDataTest {
@Test
public void test1() {
DataSyncService dataSyncService = new DataSyncService();
dataSyncService.sync(DataSyncConfig.builder()
// 读取
// postgresSQL
// .sourceDriver(DriverType.postgresSQL)
// .sourceUrl("jdbc:postgresql://192.168.1.28:5432/tianhe-police-intelligence?currentSchema=public")
// .sourceSchema("public")
// .sourceUser("postgres")
// .sourcePass("password")
// .sourceTable("PLSG_TRAVEL_APPLY")
// .sqlSelect("SELECT * FROM PLSG_TRAVEL_APPLY WHERE CREATE_TIME > ?::TIMESTAMP")
// MySQL
// .sourceDriver(DriverType.mysqlCJ)
// .sourceUrl("jdbc:mysql://localhost:3306/plsg?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8")
// .sourceSchema("plsg")
// .sourceUser("root")
// .sourcePass("password")
// .sourceTable("PLSG_TRAVEL_APPLY")
// .sqlSelect("SELECT * FROM PLSG_TRAVEL_APPLY WHERE CREATE_TIME > ?")
// oracle
.sourceDriver(DriverType.oracle7AndThen)
.sourceUrl("jdbc:oracle:thin:@192.168.1.28:1521/ORCL")
.sourceSchema("PLSG")
.sourceUser("PLSG")
.sourcePass("PLSG")
.sourceTable("PLSG_TRAVEL_APPLY")
.sqlSelect("SELECT * FROM PLSG_TRAVEL_APPLY WHERE CREATE_TIME > TO_DATE(?,'yyyy-MM-dd HH24:mi:ss')")
// 写入
// postgresSQL
.targetDriver(DriverType.postgresSQL)
.targetUrl("jdbc:postgresql://192.168.1.28:5432/tianhe-police-intelligence?currentSchema=public")
.targetSchema("public")
.targetUser("postgres")
.targetPass("password")
.targetTable("plsg_travel_apply")
.fieldUniqueKye("id")
.fieldLastSyncTime("CREATE_TIME")
.sqlLastSyncTime("SELECT MAX(CREATE_TIME) CREATE_TIME FROM plsg_travel_apply")
// mysql
// .targetDriver(DriverType.mysqlCJ)
// .targetUrl("jdbc:mysql://localhost:3306/plsg?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8")
// .targetSchema("plsg")
// .targetUser("root")
// .targetPass("password")
// .targetTable("plsg_travel_apply")
// .fieldLastSyncTime("CREATE_TIME")
// .sqlLastSyncTime("SELECT MAX(CREATE_TIME) CREATE_TIME FROM plsg_travel_apply")
// oracle
// .targetDriver(DriverType.oracle7AndThen)
// .targetUrl("jdbc:oracle:thin:@192.168.1.28:1521/ORCL")
// .targetSchema("PERSONNEL")
// .targetUser("PERSONNEL")
// .targetPass("PERSONNEL")
// .targetTable("PLSG_TRAVEL_APPLY")
// .fieldLastSyncTime("CREATE_TIME")
// .sqlLastSyncTime("SELECT MAX(CREATE_TIME) CREATE_TIME FROM PLSG_TRAVEL_APPLY")
.build());
}
}
PGSQL
利用 MyBatis
查询回来的 JSON 数据类型会封装成 PGobject
对象,所以这个对象如果直接返回到前端,前端需要再获取一层里面的 json
属性,并且还需要再转换一遍 JSON.parse(json)
,这里添加了 ToJSONObjectSerializer
和ToJSONArraySerializer
,搭配 @JsonSerialize()
注解可以来实现将 PGobject
对象转成 JSON
对象或者 JSON
数组。JSON
对象或者 JSON
数组到数据库,但是 Bean
的属性的类型还是得用 Object
,MyBatisUtil
会做处理转成 PGobject
存储到数据库相关信息
为了解决系统数据权限范围过滤问题,可以使用 @DataScope 注解,目前开发了基础版本,后续会陆续完善。
在使用注解前,需要了解,什么是数据权限,数据权限,即,基于用户/角色 关联绑定的部门,管理区域等一系列有父子级关系,或者无父子级关系的有标签性质的数据,单纯因为 用户/角色 关联了这些数据,用户再去访问/操作其他和这些权限关联的数据的时候,过滤掉 用户/角色 没有关联对应的权限数据的数据的操作,我们可以称之为数据权限过滤。在通常情况下,我们过滤数据权限,会写大量的过滤 sql ,或者大量的过滤逻,这里我们总结了这些过滤逻辑的通用情况下的操作,这里编写成了注解
相关信息
如果前端就知道了有后期更新数据库类型的可能性,便可以在开发的过程就做就好兼容性,方便后续直接切换数据库
这里兼容主要是基于 mybatis-plus 提供的便利性
这里,我在 spring-taybct-tool-mybatis 模块里面做了 Mybatis-plus 的基础配置,配置里面就有加入了方言的配置
@Bean
public DatabaseIdProvider databaseIdProvider() {
VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
Properties properties = new Properties();
properties.put("Oracle", "oracle");
properties.put("MySQL", "mysql");
properties.setProperty("PostgreSQL", "postgresql");
properties.setProperty("DB2", "db2");
properties.setProperty("SQL Server", "sqlserver");
databaseIdProvider.setProperties(properties);
return databaseIdProvider;
}
相关信息
强制登出用户的时候,需要处理用户缓存,或者修改了角色,需要强制拿出这些角色相关的用户的话,需要开发人员自行决定是否要这样做。下面这两个配置类,需要放在 system 模块下
@Component
@RequiredArgsConstructor
public class LoginCacheClear implements ILoginCacheClear {
final RedisTemplate<Object, Object> redisTemplate;
@Override
public void accept(Collection<SysUser> sysUsers) {
redisTemplate.delete(sysUsers.stream()
.map(user -> Arrays.asList(
//TODO 这里有多少种登录方式就得加多少种,用户名,包含了邮箱
CacheConstants.OAuth.USERNAME + "::" +user.getUsername(),
CacheConstants.OAuth.OPENID + "::" + user.getUsername(),
CacheConstants.OAuth.PHONE + "::" + user.getPhone(),
CacheConstants.OAuth.USERID + "::" + user.getId()
))
.flatMap(Collection::stream)
.collect(Collectors.toSet()));
}
}
相关信息
我们在做数据库操作,写 xml sql 语句的时候,一些通用的参数,或者我们想添加一个并不是实体类里面有的参数,我们的处理方式可能是加一个 VO,或者 DTO 类来实现,或者是在方法里面多写一些的参数,但是,其实可以把这些参数,通过 MyBatis 拦截器的方式添加到参数里面,然后就可以在 XML 里面调用来写动态 SQL 了,框架使用了 MyBatisExtraParamsInterceptor 拦截器用来添加额外参数
相关信息
在项目开发中如果需要让程序自动在某个时刻去执行一些命令,就需要使用到任务调度
引入依赖 spring-taybct-tool-scheduling
<!--任务调度-->
<dependency>
<groupId>io.github.mangocrisp</groupId>
<artifactId>spring-taybct-tool-scheduling</artifactId>
</dependency>
https://sentinelguard.io/zh-cn/