重构mybatis-jpa结构,解决更新null的bug

This commit is contained in:
Dftre 2024-05-25 02:16:43 +08:00
parent b47a0a6937
commit 574625555b
9 changed files with 201 additions and 174 deletions

View File

@ -16,6 +16,14 @@ public class BaseColumnInfo {
return getTemplate(false); return getTemplate(false);
} }
public String getColumnName() {
return columnName;
}
public String getUnqualifiedColumnName() {
return columnName;
}
public String getTemplate(boolean params) { public String getTemplate(boolean params) {
if (params) { if (params) {
return "#{params." + fieldName + "}"; return "#{params." + fieldName + "}";

View File

@ -21,10 +21,6 @@ public class ColumnInfo extends BaseColumnInfo {
this.querySql = this.getQuerySql(this.query); this.querySql = this.getQuerySql(this.query);
} }
public String getColumnName() {
return columnName;
}
public boolean isPrimaryKey() { public boolean isPrimaryKey() {
return this.column.primaryKey(); return this.column.primaryKey();
} }
@ -36,4 +32,8 @@ public class ColumnInfo extends BaseColumnInfo {
public String getQuerySql() { public String getQuerySql() {
return this.querySql; return this.querySql;
} }
public String getFullyQualifiedColumnName(String tableName) {
return tableName + "." + this.getColumnName();
}
} }

View File

@ -30,10 +30,6 @@ public class MapColumnInfo extends BaseColumnInfo {
return this.columnMap; return this.columnMap;
} }
public String getColumnName() {
return columnName;
}
public String getQuerySql(Query query) { public String getQuerySql(Query query) {
return QueryUtil.getQuerySql(this.getColumnName(), getTemplate(), query); return QueryUtil.getQuerySql(this.getColumnName(), getTemplate(), query);
} }
@ -42,4 +38,8 @@ public class MapColumnInfo extends BaseColumnInfo {
return this.columnMap.target() + "." + this.querySql; return this.columnMap.target() + "." + this.querySql;
} }
public String getFullyQualifiedColumnName() {
return this.columnMap.target() + "." + this.getColumnName();
}
} }

View File

@ -14,6 +14,7 @@ import com.ruoyi.mybatis.annotation.Column;
import com.ruoyi.mybatis.annotation.ColumnMap; import com.ruoyi.mybatis.annotation.ColumnMap;
import com.ruoyi.mybatis.annotation.EnableTableMap; import com.ruoyi.mybatis.annotation.EnableTableMap;
import com.ruoyi.mybatis.annotation.Table; import com.ruoyi.mybatis.annotation.Table;
import com.ruoyi.mybatis.utils.QueryUtil;
/** /**
* 数据库表信息 * 数据库表信息
@ -35,17 +36,16 @@ public class TableInfo {
if (this.table == null) if (this.table == null)
throw new RuntimeException("error , not find tableName"); throw new RuntimeException("error , not find tableName");
this.tableName = this.table.name(); this.tableName = this.table.name();
// 获取所有标记Column注解的字段
this.enableTableMap = AnnotationUtils.findAnnotation(cls, EnableTableMap.class); this.enableTableMap = AnnotationUtils.findAnnotation(cls, EnableTableMap.class);
Arrays.stream(cls.getDeclaredFields()) Arrays.stream(cls.getDeclaredFields())
.filter(field -> AnnotationUtils.findAnnotation(field, Column.class) != null) .filter(field -> AnnotationUtils.findAnnotation(field, Column.class) != null)
.map(field -> new ColumnInfo(field)) .map(ColumnInfo::new)
.forEach(this.columns::add); .forEach(this.columns::add);
Arrays.stream(cls.getDeclaredFields()) Arrays.stream(cls.getDeclaredFields())
.filter(field -> AnnotationUtils.findAnnotation(field, ColumnMap.class) != null) .filter(field -> AnnotationUtils.findAnnotation(field, ColumnMap.class) != null)
.map(field -> new MapColumnInfo(field)) .map(MapColumnInfo::new)
.forEach(this.mapColumns::add); .forEach(this.mapColumns::add);
this.getColumns().stream() this.getColumns().stream()
@ -55,42 +55,42 @@ public class TableInfo {
this.getMapColumns().stream() this.getMapColumns().stream()
.map(MapColumnInfo::getJoin) .map(MapColumnInfo::getJoin)
.map(join -> { .map(join -> {
String left = join.onLeft(); String lf = join.onLeft();
String right = join.onRight(); String rf = join.onRight();
if (StringUtils.isEmpty(left) || StringUtils.isEmpty(right)) { String lt = this.getTableNameT();
left = join.on(); String rt = join.target();
right = join.on(); if (StringUtils.isEmpty(lf) || StringUtils.isEmpty(rf)) {
lf = join.on();
rf = join.on();
} }
return join.target() + " on " return QueryUtil.getJoinSql(lt, rt, lf, rf);
+ join.target() + "." + right + " = "
+ this.getTableNameT() + "." + left;
}) })
.forEach(joinSql::add); .forEach(joinSql::add);
if (this.enableTableMap != null) { if (this.enableTableMap != null) {
if (StringUtils.isNotEmpty(this.enableTableMap.user())) { if (StringUtils.isNotEmpty(this.enableTableMap.user())) {
String left = this.enableTableMap.userOnLeft(); String lf = this.enableTableMap.userOnLeft();
String right = this.enableTableMap.userOnRight(); String rf = this.enableTableMap.userOnRight();
if (StringUtils.isEmpty(left) || StringUtils.isEmpty(right)) { String lt = this.getTableNameT();
left = this.enableTableMap.userOn(); String rt = this.enableTableMap.user();
right = this.enableTableMap.userOn(); if (StringUtils.isEmpty(lf) || StringUtils.isEmpty(rf)) {
lf = this.enableTableMap.userOn();
rf = this.enableTableMap.userOn();
} }
this.joinSql.add("sys_user " + this.enableTableMap.user() + " on " this.joinSql.add("sys_user " + QueryUtil.getJoinSql(lt, rt, lf, rf));
+ this.enableTableMap.user() + "." + right + " = "
+ this.getTableNameT() + "." + left);
this.hasDataScopeValue = true; this.hasDataScopeValue = true;
} }
if (StringUtils.isNotEmpty(this.enableTableMap.dept())) { if (StringUtils.isNotEmpty(this.enableTableMap.dept())) {
String left = this.enableTableMap.deptOnLeft(); String lf = this.enableTableMap.deptOnLeft();
String right = this.enableTableMap.deptOnRight(); String rf = this.enableTableMap.deptOnRight();
if (StringUtils.isEmpty(right) || StringUtils.isEmpty(left)) { String lt = this.getTableNameT();
left = this.enableTableMap.deptOn(); String rt = this.enableTableMap.dept();
right = this.enableTableMap.deptOn(); if (StringUtils.isEmpty(lf) || StringUtils.isEmpty(rf)) {
lf = this.enableTableMap.deptOn();
rf = this.enableTableMap.deptOn();
} }
this.joinSql.add("sys_dept " + this.enableTableMap.dept() + " on " this.joinSql.add("sys_dept " + QueryUtil.getJoinSql(lt, rt, lf, rf));
+ this.enableTableMap.dept() + "." + right + " = "
+ this.getTableNameT() + "." + left);
this.hasDataScopeValue = true; this.hasDataScopeValue = true;
} }
} }
@ -135,7 +135,7 @@ public class TableInfo {
.map(column -> this.getTableNameT() + "." + column) .map(column -> this.getTableNameT() + "." + column)
.collect(Collectors.toList()); .collect(Collectors.toList());
this.mapColumns.stream() this.mapColumns.stream()
.map(column -> column.getJoin().target() + "." + column.getColumnName()) .map(MapColumnInfo::getFullyQualifiedColumnName)
.forEach(columns::add); .forEach(columns::add);
} }
@ -153,7 +153,7 @@ public class TableInfo {
.map(column -> this.getTableNameT() + "." + column) .map(column -> this.getTableNameT() + "." + column)
.collect(Collectors.toList()); .collect(Collectors.toList());
this.mapColumns.stream() this.mapColumns.stream()
.map(column -> column.getJoin().target() + "." + column.getColumnName()) .map(MapColumnInfo::getFullyQualifiedColumnName)
.forEach(columns::add); .forEach(columns::add);
} }

View File

@ -9,22 +9,22 @@ import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider; import org.apache.ibatis.annotations.UpdateProvider;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.mybatis.utils.SQLUtil; import com.ruoyi.mybatis.utils.SQLGenerator;
public interface JPAMapper<T extends BaseEntity> { public interface JPAMapper<T extends BaseEntity> {
@SelectProvider(value = SQLUtil.class, method = "selectById") @SelectProvider(value = SQLGenerator.class, method = SQLGenerator.Method.SELECT_BY_ID)
public T selectById(T entity); public T selectById(T entity);
@SelectProvider(value = SQLUtil.class, method = "list") @SelectProvider(value = SQLGenerator.class, method = SQLGenerator.Method.LIST)
public List<T> selectList(T entity); public List<T> selectList(T entity);
@InsertProvider(value = SQLUtil.class, method = "insert") @InsertProvider(value = SQLGenerator.class, method = SQLGenerator.Method.INSERT)
@Options(useGeneratedKeys = true) @Options(useGeneratedKeys = true)
public int insert(T entity); public int insert(T entity);
@UpdateProvider(value = SQLUtil.class, method = "update") @UpdateProvider(value = SQLGenerator.class, method = SQLGenerator.Method.UPDATE)
public int update(T entity); public int update(T entity);
@DeleteProvider(value = SQLUtil.class, method = "deleteById") @DeleteProvider(value = SQLGenerator.class, method = SQLGenerator.Method.DELETE_BY_ID)
public int deleteById(T entity); public int deleteById(T entity);
} }

View File

@ -51,6 +51,12 @@ public class QueryUtil {
} }
} }
public static String getJoinSql(String leftTable, String rightTable, String leftField, String rightField) {
return rightTable + " on "
+ leftTable + "." + leftField + " = "
+ rightTable + "." + rightField;
}
public static String getQuerySql(String column, String iField, Query query) { public static String getQuerySql(String column, String iField, Query query) {
if (query == null) if (query == null)
return ""; return "";

View File

@ -0,0 +1,114 @@
package com.ruoyi.mybatis.utils;
import java.util.Arrays;
import org.apache.ibatis.jdbc.SQL;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.mybatis.domain.ColumnInfo;
import com.ruoyi.mybatis.domain.MapColumnInfo;
import com.ruoyi.mybatis.domain.TableInfo;
public class SQLGenerator {
public static class Method {
public final static String LIST = "list";
public final static String INSERT = "insert";
public final static String UPDATE = "update";
public final static String SELECT_BY_ID = "selectById";
public final static String DELETE_BY_ID = "deleteById";
}
public static <T extends BaseEntity> String list(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = TableContainer.getTableInfo(entity);
sql.SELECT(String.join(",", tableInfo.getQueryColumnNames()))
.FROM(tableInfo.getTableNameFrom());
if (tableInfo.isEnbleMap()) {
tableInfo.getJoinSql().stream()
.filter(StringUtils::isNotEmpty)
.forEach(sql::LEFT_OUTER_JOIN);
tableInfo.getNotNullMapColumnsForQuery(entity).stream()
.map(MapColumnInfo::getQuerySql)
.forEach(sql::WHERE);
tableInfo.getNotNullColumnsForQuery(entity).stream()
.map(ColumnInfo::getQuerySql)
.map(query -> tableInfo.getTableNameT() + "." + query)
.forEach(sql::WHERE);
if (tableInfo.hasDataScope()) {
sql.WHERE("1=1 ${params.dataScope}");
}
Arrays.stream(tableInfo.getOrderBy())
.filter(StringUtils::isNotEmpty)
.map(order -> tableInfo.getTableNameT() + "." + order)
.forEach(sql::ORDER_BY);
} else {
tableInfo.getNotNullColumnsForQuery(entity).stream()
.map(ColumnInfo::getQuerySql)
.filter(StringUtils::isNotEmpty)
.forEach(sql::WHERE);
Arrays.stream(tableInfo.getOrderBy())
.filter(StringUtils::isNotEmpty)
.forEach(sql::ORDER_BY);
}
return sql.toString();
}
public static <T extends BaseEntity> String insert(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = TableContainer.getTableInfo(entity);
sql.INSERT_INTO(tableInfo.getTableName());
tableInfo.getNotNullColumns(entity).stream()
.forEach(column -> sql.VALUES(column.getColumnName(), column.getTemplate()));
return sql.toString();
}
public static <T extends BaseEntity> String update(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = TableContainer.getTableInfo(entity);
sql.UPDATE(tableInfo.getTableName());
tableInfo.getPrimaryKeys().stream()
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::WHERE);
tableInfo.getNotNullColumns(entity).stream()
.filter(column -> !column.isPrimaryKey())
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::SET);
return sql.toString();
}
public static <T extends BaseEntity> String deleteById(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = TableContainer.getTableInfo(entity);
sql.DELETE_FROM(tableInfo.getTableName());
tableInfo.getPrimaryKeys().stream()
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::WHERE);
return sql.toString();
}
public static <T extends BaseEntity> String selectById(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = TableContainer.getTableInfo(entity);
sql.SELECT(String.join(",", tableInfo.getColumnNames()))
.FROM(tableInfo.getTableNameFrom());
if (tableInfo.isEnbleMap()) {
tableInfo.getJoinSql().stream()
.forEach(sql::LEFT_OUTER_JOIN);
tableInfo.getPrimaryKeys().stream()
.map(column -> tableInfo.getTableNameT() + "." + column.getColumnName() + " = "
+ column.getTemplate())
.forEach(sql::WHERE);
} else {
tableInfo.getPrimaryKeys().stream()
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::WHERE);
}
return sql.toString();
}
}

View File

@ -1,131 +0,0 @@
package com.ruoyi.mybatis.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.jdbc.SQL;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.mybatis.domain.ColumnInfo;
import com.ruoyi.mybatis.domain.MapColumnInfo;
import com.ruoyi.mybatis.domain.TableInfo;
/**
* sql构建工具
*
* @author Dftre
*/
public class SQLUtil {
private static final Map<Class<?>, TableInfo> tableInfoMap = new HashMap<>();
private static <T extends BaseEntity> TableInfo getTableInfo(T entity) {
Class<?> clazz = entity.getClass();
TableInfo tableInfo = tableInfoMap.get(clazz);
if (tableInfo == null)
tableInfo = new TableInfo(clazz);
return tableInfo;
}
public static <T extends BaseEntity> String list(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = getTableInfo(entity);
sql.SELECT(String.join(",", tableInfo.getQueryColumnNames()))
.FROM(tableInfo.getTableNameFrom());
if (tableInfo.isEnbleMap()) {
tableInfo.getJoinSql().stream()
.filter(StringUtils::isNotEmpty)
.forEach(sql::LEFT_OUTER_JOIN);
tableInfo.getNotNullMapColumnsForQuery(entity).stream()
.map(MapColumnInfo::getQuerySql)
.forEach(sql::WHERE);
tableInfo.getNotNullColumnsForQuery(entity).stream()
.map(ColumnInfo::getQuerySql)
.map(query -> tableInfo.getTableNameT() + "." + query)
.forEach(sql::WHERE);
if (tableInfo.hasDataScope()) {
sql.WHERE("1=1 ${params.dataScope}");
}
Arrays.stream(tableInfo.getOrderBy())
.filter(StringUtils::isNotEmpty)
.map(order -> tableInfo.getTableNameT() + "." + order)
.forEach(sql::ORDER_BY);
} else {
tableInfo.getNotNullColumnsForQuery(entity).stream()
.map(ColumnInfo::getQuerySql)
.filter(StringUtils::isNotEmpty)
.forEach(sql::WHERE);
Arrays.stream(tableInfo.getOrderBy())
.filter(StringUtils::isNotEmpty)
.forEach(sql::ORDER_BY);
}
return sql.toString();
}
public static <T extends BaseEntity> String insert(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = getTableInfo(entity);
sql.INSERT_INTO(tableInfo.getTableName());
tableInfo.getNotNullColumns(entity).stream()
.forEach(column -> sql.VALUES(column.getColumnName(), column.getTemplate()));
return sql.toString();
}
public static <T extends BaseEntity> String update(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = getTableInfo(entity);
sql.UPDATE(tableInfo.getTableName());
List<String> sets = new ArrayList<String>();
tableInfo.getColumns().stream()
.forEach(column -> {
if (column.isPrimaryKey()) {
sql.WHERE(column.getColumnName() + " = " + column.getTemplate());
} else {
sets.add(column.getColumnName() + " = " + column.getTemplate());
}
});
sql.SET(sets.toArray(new String[0]));
return sql.toString();
}
public static <T extends BaseEntity> String deleteById(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = getTableInfo(entity);
sql.DELETE_FROM(tableInfo.getTableName());
tableInfo.getPrimaryKeys().stream()
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::WHERE);
return sql.toString();
}
public static <T extends BaseEntity> String selectById(T entity) {
SQL sql = new SQL();
TableInfo tableInfo = getTableInfo(entity);
sql.SELECT(String.join(",", tableInfo.getColumnNames()))
.FROM(tableInfo.getTableNameFrom());
if (tableInfo.isEnbleMap()) {
tableInfo.getJoinSql().stream()
.forEach(sql::LEFT_OUTER_JOIN);
tableInfo.getPrimaryKeys().stream()
.map(column -> tableInfo.getTableNameT() + "." + column.getColumnName() + " = "
+ column.getTemplate())
.forEach(sql::WHERE);
} else {
tableInfo.getPrimaryKeys().stream()
.map(column -> column.getColumnName() + " = " + column.getTemplate())
.forEach(sql::WHERE);
}
return sql.toString();
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.mybatis.utils;
import java.util.HashMap;
import java.util.Map;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.mybatis.domain.TableInfo;
/**
* sql构建工具
*
* @author Dftre
*/
public class TableContainer {
private static final Map<Class<?>, TableInfo> tableInfoMap = new HashMap<>();
public static <T extends BaseEntity> TableInfo getTableInfo(T entity) {
Class<?> clazz = entity.getClass();
return getTableInfo(clazz);
}
public static <T extends BaseEntity> TableInfo getTableInfo(Class<?> clazz) {
TableInfo tableInfo = tableInfoMap.get(clazz);
if (tableInfo == null)
tableInfo = new TableInfo(clazz);
return tableInfo;
}
}