mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-08 16:57:09 +08:00
feat(extension/crud-mf): 支持Mybatis Flex
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?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>top.continew</groupId>
|
||||
<artifactId>continew-starter-data</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-starter-data-mybatis-flex</artifactId>
|
||||
<description>ContiNew Starter 数据访问模块 - MyBatis Flex</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Plus(MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率) -->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据访问模块 - 核心模块 -->
|
||||
<dependency>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-data-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- CosId(通用、灵活、高性能的分布式 ID 生成器) -->
|
||||
<dependency>
|
||||
<groupId>me.ahoo.cosid</groupId>
|
||||
<artifactId>cosid-spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.autoconfigure;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import top.continew.starter.core.constant.PropertiesConstants;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 是否启用数据权限注解
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Documented
|
||||
@ConditionalOnProperty(prefix = "mybatis-flex.extension.data-permission", name = PropertiesConstants.ENABLED, havingValue = "true")
|
||||
public @interface ConditionalOnEnabledDataPermission {
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.autoconfigure;
|
||||
|
||||
import com.mybatisflex.core.dialect.DbType;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* MyBatis Plus 扩展配置属性
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "mybatis-flex.extension")
|
||||
public class MyBatisFlexExtensionProperties {
|
||||
|
||||
/**
|
||||
* 是否启用扩展
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Mapper 接口扫描包(配置时必须使用:mapper-package 键名)
|
||||
* <p>
|
||||
* e.g. com.example.**.mapper
|
||||
* </p>
|
||||
*/
|
||||
private String mapperPackage;
|
||||
|
||||
/**
|
||||
* 数据权限插件配置
|
||||
*/
|
||||
private DataPermissionProperties dataPermission;
|
||||
|
||||
/**
|
||||
* 分页插件配置
|
||||
*/
|
||||
private PaginationProperties pagination;
|
||||
|
||||
/**
|
||||
* 数据权限插件配置属性
|
||||
*/
|
||||
public static class DataPermissionProperties {
|
||||
|
||||
/**
|
||||
* 是否启用数据权限插件
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页插件配置属性
|
||||
*/
|
||||
public static class PaginationProperties {
|
||||
|
||||
/**
|
||||
* 是否启用分页插件
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* 数据库类型
|
||||
*/
|
||||
private DbType dbType;
|
||||
|
||||
/**
|
||||
* 是否溢出处理
|
||||
*/
|
||||
private boolean overflow = false;
|
||||
|
||||
/**
|
||||
* 单页分页条数限制(默认:-1 表示无限制)
|
||||
*/
|
||||
private Long maxLimit = -1L;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public DbType getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
public void setDbType(DbType dbType) {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public boolean isOverflow() {
|
||||
return overflow;
|
||||
}
|
||||
|
||||
public void setOverflow(boolean overflow) {
|
||||
this.overflow = overflow;
|
||||
}
|
||||
|
||||
public Long getMaxLimit() {
|
||||
return maxLimit;
|
||||
}
|
||||
|
||||
public void setMaxLimit(Long maxLimit) {
|
||||
this.maxLimit = maxLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getMapperPackage() {
|
||||
return mapperPackage;
|
||||
}
|
||||
|
||||
public void setMapperPackage(String mapperPackage) {
|
||||
this.mapperPackage = mapperPackage;
|
||||
}
|
||||
|
||||
public DataPermissionProperties getDataPermission() {
|
||||
return dataPermission;
|
||||
}
|
||||
|
||||
public void setDataPermission(DataPermissionProperties dataPermission) {
|
||||
this.dataPermission = dataPermission;
|
||||
}
|
||||
|
||||
public PaginationProperties getPagination() {
|
||||
return pagination;
|
||||
}
|
||||
|
||||
public void setPagination(PaginationProperties pagination) {
|
||||
this.pagination = pagination;
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.autoconfigure;
|
||||
|
||||
import com.mybatisflex.core.dialect.DbType;
|
||||
import com.mybatisflex.core.dialect.DialectFactory;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import top.continew.starter.core.constant.PropertiesConstants;
|
||||
import top.continew.starter.core.util.GeneralPropertySourceFactory;
|
||||
import top.continew.starter.data.mybatis.flex.datapermission.DataPermissionDialect;
|
||||
import top.continew.starter.data.mybatis.flex.datapermission.DataPermissionFilter;
|
||||
|
||||
/**
|
||||
* MyBatis Flex 自动配置
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@MapperScan("${mybatis-flex.extension.mapper-package}")
|
||||
@EnableTransactionManagement(proxyTargetClass = true)
|
||||
@EnableConfigurationProperties(MyBatisFlexExtensionProperties.class)
|
||||
@ConditionalOnProperty(prefix = "mybatis-flex.extension", name = PropertiesConstants.ENABLED, havingValue = "true")
|
||||
@PropertySource(value = "classpath:default-data-mybatis-flex.yml", factory = GeneralPropertySourceFactory.class)
|
||||
public class MybatisFlexAutoConfiguration {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MybatisFlexAutoConfiguration.class);
|
||||
|
||||
@Resource
|
||||
private DataPermissionFilter dataPermissionFilter;
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
log.debug("[ContiNew Starter] - Auto Configuration 'MyBatis Flex' completed initialization.");
|
||||
DialectFactory.registerDialect(DbType.MYSQL, new DataPermissionDialect(dataPermissionFilter));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.base;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Db;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Mapper 基类
|
||||
*
|
||||
* @param <T> 实体类
|
||||
* @author hellokaton
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface BaseMapper<T> extends com.mybatisflex.core.BaseMapper<T> {
|
||||
|
||||
/**
|
||||
* 批量更新记录
|
||||
*
|
||||
* @param entityList 实体列表
|
||||
* @return 是否成功
|
||||
*/
|
||||
default boolean updateBatchById(Collection<T> entityList) {
|
||||
return Db.updateEntitiesBatch(entityList) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 链式查询
|
||||
*
|
||||
* @return QueryWrapper 的包装类
|
||||
*/
|
||||
default QueryWrapper query() {
|
||||
return QueryWrapper.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* 链式查询
|
||||
*
|
||||
* @return QueryWrapper 的包装类
|
||||
*/
|
||||
default QueryWrapper query(T entity) {
|
||||
return QueryWrapper.create(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体类 Class 对象
|
||||
*
|
||||
* @return 实体类 Class 对象
|
||||
*/
|
||||
default Class<T> currentEntityClass() {
|
||||
return (Class<T>)ClassUtil.getTypeArgument(this.getClass(), 0);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.base;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 枚举接口
|
||||
*
|
||||
* @param <T> value 类型
|
||||
* @author hellokaton
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface IBaseEnum<T extends Serializable> {
|
||||
|
||||
/**
|
||||
* 枚举描述
|
||||
*
|
||||
* @return 枚举描述
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* 枚举数据库存储值
|
||||
*/
|
||||
T getValue();
|
||||
|
||||
/**
|
||||
* 颜色
|
||||
*
|
||||
* @return 颜色
|
||||
*/
|
||||
default String getColor() {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 数据权限注解
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DataPermission {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #tableAlias()} attribute.
|
||||
*/
|
||||
@AliasFor("tableAlias")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* 表别名
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String tableAlias() default "";
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
String id() default "id";
|
||||
|
||||
/**
|
||||
* 部门 ID
|
||||
*/
|
||||
String deptId() default "dept_id";
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
String userId() default "create_user";
|
||||
|
||||
/**
|
||||
* 角色 ID(角色和部门关联表)
|
||||
*/
|
||||
String roleId() default "role_id";
|
||||
|
||||
/**
|
||||
* 部门表别名
|
||||
*/
|
||||
String deptTableAlias() default "sys_dept";
|
||||
|
||||
/**
|
||||
* 角色和部门关联表别名
|
||||
*/
|
||||
String roleDeptTableAlias() default "sys_role_dept";
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
import org.aspectj.lang.annotation.*;
|
||||
|
||||
@Aspect
|
||||
public class DataPermissionAspect {
|
||||
|
||||
// ThreadLocal用于存储注解信息
|
||||
private static final ThreadLocal<DataPermission> THREAD_LOCAL = new ThreadLocal<>();
|
||||
|
||||
@Pointcut("@annotation(dataPermission)")
|
||||
public void dataPermissionPointcut(DataPermission dataPermission) {
|
||||
}
|
||||
|
||||
@Before("dataPermissionPointcut(dataPermission)")
|
||||
public void beforeMethod(DataPermission dataPermission) {
|
||||
THREAD_LOCAL.set(dataPermission);
|
||||
}
|
||||
|
||||
@AfterThrowing(pointcut = "dataPermissionPointcut(dataPermission)")
|
||||
public void afterThrowingMethod(DataPermission dataPermission) {
|
||||
THREAD_LOCAL.remove();
|
||||
}
|
||||
|
||||
@After("dataPermissionPointcut(dataPermission)")
|
||||
public void afterMethod(DataPermission dataPermission) {
|
||||
THREAD_LOCAL.remove();
|
||||
}
|
||||
|
||||
public static DataPermission currentDataPermission() {
|
||||
return THREAD_LOCAL.get();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 当前用户信息
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public class DataPermissionCurrentUser {
|
||||
|
||||
/**
|
||||
* 用户 ID
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 角色列表
|
||||
*/
|
||||
private Set<CurrentUserRole> roles;
|
||||
|
||||
/**
|
||||
* 部门 ID
|
||||
*/
|
||||
private String deptId;
|
||||
|
||||
/**
|
||||
* 当前用户角色信息
|
||||
*/
|
||||
public static class CurrentUserRole {
|
||||
|
||||
/**
|
||||
* 角色 ID
|
||||
*/
|
||||
private String roleId;
|
||||
|
||||
/**
|
||||
* 数据权限
|
||||
*/
|
||||
private DataScope dataScope;
|
||||
|
||||
public CurrentUserRole() {
|
||||
}
|
||||
|
||||
public CurrentUserRole(String roleId, DataScope dataScope) {
|
||||
this.roleId = roleId;
|
||||
this.dataScope = dataScope;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(String roleId) {
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public DataScope getDataScope() {
|
||||
return dataScope;
|
||||
}
|
||||
|
||||
public void setDataScope(DataScope dataScope) {
|
||||
this.dataScope = dataScope;
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Set<CurrentUserRole> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(Set<CurrentUserRole> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public String getDeptId() {
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(String deptId) {
|
||||
this.deptId = deptId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 数据权限处理器实现类
|
||||
*
|
||||
* @author <a href="https://mybatis-flex.com/zh/core/data-permission.html">数据权限</a>
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public class DataPermissionDialect extends CommonsDialectImpl {
|
||||
|
||||
private final DataPermissionFilter dataPermissionFilter;
|
||||
|
||||
public DataPermissionDialect(DataPermissionFilter dataPermissionFilter) {
|
||||
this.dataPermissionFilter = dataPermissionFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String forSelectByQuery(QueryWrapper queryWrapper) {
|
||||
if (!dataPermissionFilter.isFilter()) {
|
||||
return super.buildSelectSql(queryWrapper);
|
||||
}
|
||||
DataPermission dataPermission = DataPermissionAspect.currentDataPermission();
|
||||
if (null == dataPermission) {
|
||||
return super.buildSelectSql(queryWrapper);
|
||||
}
|
||||
DataPermissionCurrentUser currentUser = dataPermissionFilter.getCurrentUser();
|
||||
Set<DataPermissionCurrentUser.CurrentUserRole> roles = currentUser.getRoles();
|
||||
for (DataPermissionCurrentUser.CurrentUserRole role : roles) {
|
||||
DataScope dataScope = role.getDataScope();
|
||||
if (DataScope.ALL.equals(dataScope)) {
|
||||
return super.buildSelectSql(queryWrapper);
|
||||
}
|
||||
switch (dataScope) {
|
||||
case DEPT_AND_CHILD -> this.buildDeptAndChildExpression(dataPermission, currentUser, queryWrapper);
|
||||
case DEPT -> this.buildDeptExpression(dataPermission, currentUser, queryWrapper);
|
||||
case SELF -> this.buildSelfExpression(dataPermission, currentUser, queryWrapper);
|
||||
case CUSTOM -> this.buildCustomExpression(dataPermission, role, queryWrapper);
|
||||
default -> throw new IllegalArgumentException("暂不支持 [%s] 数据权限".formatted(dataScope));
|
||||
}
|
||||
}
|
||||
return super.buildSelectSql(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建自定义数据权限表达式
|
||||
*
|
||||
* <p>
|
||||
* 处理完后的 SQL 示例:<br /> select t1.* from table as t1 where t1.dept_id in (select dept_id from sys_role_dept
|
||||
* where role_id = xxx);
|
||||
* </p>
|
||||
*
|
||||
* @param dataPermission 数据权限
|
||||
* @param role 当前用户角色
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 处理完后的表达式
|
||||
*/
|
||||
private void buildCustomExpression(DataPermission dataPermission,
|
||||
DataPermissionCurrentUser.CurrentUserRole role,
|
||||
QueryWrapper queryWrapper) {
|
||||
QueryWrapper subQueryWrapper = QueryWrapper.create();
|
||||
subQueryWrapper.select(dataPermission.deptId()).from(dataPermission.roleDeptTableAlias());
|
||||
subQueryWrapper.eq(dataPermission.roleId(), role.getRoleId());
|
||||
queryWrapper.in(buildColumn(dataPermission.tableAlias(), dataPermission.deptId()), subQueryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建仅本人数据权限表达式
|
||||
*
|
||||
* <p>
|
||||
* 处理完后的 SQL 示例:<br /> select t1.* from table as t1 where t1.create_user = xxx;
|
||||
* </p>
|
||||
*
|
||||
* @param dataPermission 数据权限
|
||||
* @param currentUser 当前用户
|
||||
* @param queryWrapper 处理前的表达式
|
||||
*/
|
||||
private void buildSelfExpression(DataPermission dataPermission,
|
||||
DataPermissionCurrentUser currentUser,
|
||||
QueryWrapper queryWrapper) {
|
||||
queryWrapper.eq(buildColumn(dataPermission.tableAlias(), dataPermission.userId()), currentUser.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建本部门数据权限表达式
|
||||
*
|
||||
* <p>
|
||||
* 处理完后的 SQL 示例:<br /> select t1.* from table as t1 where t1.dept_id = xxx;
|
||||
* </p>
|
||||
*
|
||||
* @param dataPermission 数据权限
|
||||
* @param currentUser 当前用户
|
||||
* @param queryWrapper 查询条件
|
||||
*/
|
||||
private void buildDeptExpression(DataPermission dataPermission,
|
||||
DataPermissionCurrentUser currentUser,
|
||||
QueryWrapper queryWrapper) {
|
||||
queryWrapper.eq(buildColumn(dataPermission.tableAlias(), dataPermission.deptId()), currentUser.getDeptId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建本部门及以下数据权限表达式
|
||||
*
|
||||
* <p>
|
||||
* 处理完后的 SQL 示例:<br /> select t1.* from table as t1 where t1.dept_id in (select id from sys_dept where id =
|
||||
* xxx or find_in_set(xxx, ancestors));
|
||||
* </p>
|
||||
*
|
||||
* @param dataPermission 数据权限
|
||||
* @param currentUser 当前用户
|
||||
* @param queryWrapper 查询条件
|
||||
*/
|
||||
private void buildDeptAndChildExpression(DataPermission dataPermission,
|
||||
DataPermissionCurrentUser currentUser,
|
||||
QueryWrapper queryWrapper) {
|
||||
QueryWrapper subQueryWrapper = QueryWrapper.create();
|
||||
subQueryWrapper.select(dataPermission.id()).from(dataPermission.deptTableAlias());
|
||||
subQueryWrapper.and(qw -> {
|
||||
qw.eq(dataPermission.id(), currentUser.getDeptId())
|
||||
.or("find_in_set(" + currentUser.getDeptId() + ",ancestors)");
|
||||
});
|
||||
queryWrapper.in(buildColumn(dataPermission.tableAlias(), dataPermission.deptId()), subQueryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 Column
|
||||
*
|
||||
* @param tableAlias 表别名
|
||||
* @param columnName 字段名称
|
||||
* @return 带表别名字段
|
||||
*/
|
||||
private String buildColumn(String tableAlias, String columnName) {
|
||||
if (StrUtil.isNotEmpty(tableAlias)) {
|
||||
return "%s.%s".formatted(tableAlias, columnName);
|
||||
}
|
||||
return columnName;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
/**
|
||||
* 数据权限过滤器接口
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public interface DataPermissionFilter {
|
||||
|
||||
/**
|
||||
* 是否过滤
|
||||
*
|
||||
* @return true:过滤;false:不过滤
|
||||
*/
|
||||
boolean isFilter();
|
||||
|
||||
/**
|
||||
* 获取当前用户信息
|
||||
*
|
||||
* @return 当前用户信息
|
||||
*/
|
||||
DataPermissionCurrentUser getCurrentUser();
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.datapermission;
|
||||
|
||||
/**
|
||||
* 数据权限枚举
|
||||
*
|
||||
* @author hellokaton
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public enum DataScope {
|
||||
|
||||
/**
|
||||
* 全部数据权限
|
||||
*/
|
||||
ALL,
|
||||
|
||||
/**
|
||||
* 本部门及以下数据权限
|
||||
*/
|
||||
DEPT_AND_CHILD,
|
||||
|
||||
/**
|
||||
* 本部门数据权限
|
||||
*/
|
||||
DEPT,
|
||||
|
||||
/**
|
||||
* 仅本人数据权限
|
||||
*/
|
||||
SELF,
|
||||
|
||||
/**
|
||||
* 自定义数据权限
|
||||
*/
|
||||
CUSTOM,
|
||||
}
|
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.query;
|
||||
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import top.continew.starter.core.exception.BadRequestException;
|
||||
import top.continew.starter.core.util.ReflectUtils;
|
||||
import top.continew.starter.core.util.validate.ValidationUtils;
|
||||
import top.continew.starter.data.core.annotation.Query;
|
||||
import top.continew.starter.data.core.annotation.QueryIgnore;
|
||||
import top.continew.starter.data.core.enums.QueryType;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* QueryWrapper 助手
|
||||
*
|
||||
* @author hellokaton
|
||||
* @author Jasmine
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class QueryWrapperHelper {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(QueryWrapperHelper.class);
|
||||
|
||||
private QueryWrapperHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param <Q> 查询条件数据类型
|
||||
* @param <R> 查询数据类型
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
public static <Q, R> QueryWrapper build(Q query) {
|
||||
QueryWrapper queryWrapper = QueryWrapper.create();
|
||||
// 没有查询条件,直接返回
|
||||
if (null == query) {
|
||||
return queryWrapper;
|
||||
}
|
||||
// 获取查询条件中所有的字段
|
||||
List<Field> fieldList = ReflectUtils.getNonStaticFields(query.getClass());
|
||||
return build(query, fieldList, queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 QueryWrapper
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param fields 查询条件字段列表
|
||||
* @param queryWrapper QueryWrapper
|
||||
* @param <Q> 查询条件数据类型
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
public static <Q> QueryWrapper build(Q query, List<Field> fields, QueryWrapper queryWrapper) {
|
||||
// 没有查询条件,直接返回
|
||||
if (null == query) {
|
||||
return queryWrapper;
|
||||
}
|
||||
// 解析并拼接查询条件
|
||||
for (Field field : fields) {
|
||||
List<Consumer<QueryWrapper>> consumers = buildWrapperConsumer(query, field);
|
||||
if (CollUtil.isNotEmpty(consumers)) {
|
||||
consumers.forEach(queryWrapper::and);
|
||||
}
|
||||
}
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 QueryWrapper Consumer
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param field 查询条件字段
|
||||
* @param <Q> 查询条件数据类型
|
||||
* @param <R> 查询数据类型
|
||||
* @return QueryWrapper Consumer
|
||||
*/
|
||||
private static <Q, R> List<Consumer<QueryWrapper>> buildWrapperConsumer(Q query, Field field) {
|
||||
boolean accessible = field.canAccess(query);
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
// 如果字段值为空,直接返回
|
||||
Object fieldValue = field.get(query);
|
||||
if (ObjectUtil.isEmpty(fieldValue)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 设置了 @QueryIgnore 注解,直接忽略
|
||||
QueryIgnore queryIgnoreAnnotation = field.getAnnotation(QueryIgnore.class);
|
||||
if (null != queryIgnoreAnnotation && queryIgnoreAnnotation.value()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 建议:数据库表列建议采用下划线连接法命名,程序变量建议采用驼峰法命名
|
||||
String fieldName = field.getName();
|
||||
// 没有 @Query 注解,默认等值查询
|
||||
Query queryAnnotation = field.getAnnotation(Query.class);
|
||||
if (null == queryAnnotation) {
|
||||
return Collections.singletonList(q -> q.eq(CharSequenceUtil.toUnderlineCase(fieldName), fieldValue));
|
||||
}
|
||||
// 解析单列查询
|
||||
QueryType queryType = queryAnnotation.type();
|
||||
String[] columns = queryAnnotation.columns();
|
||||
final int columnLength = ArrayUtil.length(columns);
|
||||
List<Consumer<QueryWrapper>> consumers = new ArrayList<>(columnLength);
|
||||
if (columnLength <= 1) {
|
||||
String columnName = columnLength == 1 ? columns[0] : CharSequenceUtil.toUnderlineCase(fieldName);
|
||||
parse(queryType, columnName, fieldValue, consumers);
|
||||
return consumers;
|
||||
}
|
||||
// 解析多列查询
|
||||
for (String column : columns) {
|
||||
parse(queryType, column, fieldValue, consumers);
|
||||
}
|
||||
return consumers;
|
||||
} catch (BadRequestException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("Build query wrapper occurred an error: {}. Query: {}, Field: {}.", e
|
||||
.getMessage(), query, field, e);
|
||||
} finally {
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析查询条件
|
||||
*
|
||||
* @param queryType 查询类型
|
||||
* @param columnName 列名
|
||||
* @param fieldValue 字段值
|
||||
* @param <R> 查询数据类型
|
||||
*/
|
||||
private static <R> void parse(QueryType queryType,
|
||||
String columnName,
|
||||
Object fieldValue,
|
||||
List<Consumer<QueryWrapper>> consumers) {
|
||||
switch (queryType) {
|
||||
case EQ -> consumers.add(q -> q.eq(columnName, fieldValue));
|
||||
case NE -> consumers.add(q -> q.ne(columnName, fieldValue));
|
||||
case GT -> consumers.add(q -> q.gt(columnName, fieldValue));
|
||||
case GE -> consumers.add(q -> q.ge(columnName, fieldValue));
|
||||
case LT -> consumers.add(q -> q.lt(columnName, fieldValue));
|
||||
case LE -> consumers.add(q -> q.le(columnName, fieldValue));
|
||||
case BETWEEN -> {
|
||||
List<Object> between = new ArrayList<>((List<Object>)fieldValue);
|
||||
ValidationUtils.throwIf(between.size() != 2, "[{}] 必须是一个范围", columnName);
|
||||
consumers.add(q -> q.between(columnName, between.get(0), between.get(1)));
|
||||
}
|
||||
case LIKE -> consumers.add(q -> q.like(columnName, fieldValue));
|
||||
case LIKE_LEFT -> consumers.add(q -> q.likeLeft(columnName, fieldValue));
|
||||
case LIKE_RIGHT -> consumers.add(q -> q.likeRight(columnName, fieldValue));
|
||||
case IN -> {
|
||||
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", columnName);
|
||||
consumers.add(q -> q.in(columnName, (Collection<Object>)fieldValue));
|
||||
}
|
||||
case NOT_IN -> {
|
||||
ValidationUtils.throwIfEmpty(fieldValue, "[{}] 不能为空", columnName);
|
||||
consumers.add(q -> q.notIn(columnName, (Collection<Object>)fieldValue));
|
||||
}
|
||||
case IS_NULL -> consumers.add(q -> q.isNull(columnName));
|
||||
case IS_NOT_NULL -> consumers.add(q -> q.isNotNull(columnName));
|
||||
default -> throw new IllegalArgumentException("暂不支持 [%s] 查询类型".formatted(queryType));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.service;
|
||||
|
||||
/**
|
||||
* 通用业务接口
|
||||
*
|
||||
* @param <T> 实体类型
|
||||
* @author hellokaton
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface IService<T> extends com.mybatisflex.core.service.IService<T> {
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.data.mybatis.flex.service.impl;
|
||||
|
||||
import top.continew.starter.core.util.ClassUtils;
|
||||
import top.continew.starter.data.mybatis.flex.base.BaseMapper;
|
||||
import top.continew.starter.data.mybatis.flex.service.IService;
|
||||
|
||||
/**
|
||||
* 通用业务实现类
|
||||
*
|
||||
* @param <M> Mapper 接口
|
||||
* @param <T> 实体类型
|
||||
* @author hellokaton
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class ServiceImpl<M extends BaseMapper<T>, T> extends com.mybatisflex.spring.service.impl.ServiceImpl<M, T> implements IService<T> {
|
||||
|
||||
protected final Class<?>[] typeArguments = ClassUtils.getTypeArguments(this.getClass());
|
||||
protected final Class<T> entityClass = currentModelClass();
|
||||
|
||||
protected Class<T> currentModelClass() {
|
||||
return (Class<T>)this.typeArguments[1];
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
top.continew.starter.data.mybatis.flex.autoconfigure.MybatisFlexAutoConfiguration
|
@@ -0,0 +1,22 @@
|
||||
--- ### MyBatis Flex 配置(https://mybatis-flex.com/zh/base/configuration.html)
|
||||
mybatis-flex:
|
||||
# 启动时是否检查 MyBatis XML 文件的存在(默认:false 不检查)
|
||||
check-config-location: true
|
||||
## MyBatis 原生支持配置
|
||||
configuration:
|
||||
# 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名)到经典 Java 属性名 aColumn(驼峰命名)的类似映射
|
||||
# 此属性在 MyBatis 中原默认值为 false,在 MyBatis-Plus 中,此属性也将用于生成最终的 SQL 的 select body,如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
|
||||
map-underscore-to-camel-case: true
|
||||
# MyBatis 自动映射时未知列或未知属性处理策略,通过该配置可指定 MyBatis 在自动映射过程中遇到未知列或者未知属性时如何处理
|
||||
# NONE:不做任何处理 (默认值);WARNING:以日志的形式打印相关警告信息;FAILING:当作映射失败处理,并抛出异常和详细信息
|
||||
auto-mapping-unknown-column-behavior: NONE
|
||||
# 日志配置
|
||||
# 默认:org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
# 更详细(会有性能损耗):org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 关闭(可单纯使用 p6spy 分析):org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
global-config:
|
||||
key-config:
|
||||
key-type: generator
|
||||
# flexId 主键生成器 com.mybatisflex.core.keygen.impl.FlexIDKeyGenerator
|
||||
value: flexId
|
@@ -16,6 +16,7 @@
|
||||
<modules>
|
||||
<module>continew-starter-data-core</module>
|
||||
<module>continew-starter-data-mybatis-plus</module>
|
||||
<module>continew-starter-data-mybatis-flex</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
Reference in New Issue
Block a user