add mybatis-jpa

This commit is contained in:
D 2024-04-11 09:26:06 +08:00
parent 1ee2a209ce
commit 3d7fa110f2
14 changed files with 640 additions and 2 deletions

11
pom.xml
View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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">
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> <modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
@ -240,6 +239,13 @@
<artifactId>ruoyi-online</artifactId> <artifactId>ruoyi-online</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- mybatis-jpa-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-mybatis-jpa</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -253,6 +259,7 @@
<module>ruoyi-oauth</module> <module>ruoyi-oauth</module>
<module>ruoyi-pay</module> <module>ruoyi-pay</module>
<module>ruoyi-online</module> <module>ruoyi-online</module>
<module>ruoyi-mybatis-jpa</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>

28
ruoyi-mybatis-jpa/pom.xml Normal file
View File

@ -0,0 +1,28 @@
<?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">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.7.3.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-mybatis-jpa</artifactId>
<description>
ruoyi-mybatis-plus模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String name(); // 对应数据库字段名
boolean primaryKey() default false; // 是否是主键
}

View File

@ -0,0 +1,14 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnMap {
String name(); // 对应数据库字段
String target(); // 映射表来源
String targetColumn(); // 映射表字段
}

View File

@ -0,0 +1,12 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EnableTableMap {
String name() default "t";
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsMap {
Class<?> value();
String[] paramToProperty();
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.mybatis.enums.QueryEnum;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Query {
QueryEnum operation() default QueryEnum.eq; // 操作符 eq, like, gt
String[] section() default { "begin", "end" };
boolean params() default false;
String sql() default "";
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
String name();
String[] columns() default {};
}

View File

@ -0,0 +1,93 @@
package com.ruoyi.mybatis.domain;
import java.lang.reflect.Field;
import org.springframework.core.annotation.AnnotationUtils;
import com.ruoyi.mybatis.annotation.Column;
import com.ruoyi.mybatis.annotation.Query;
public class ColumnInfo {
private String columnName;
private String fieldName;
private Field field;
private Column column;
private Query query;
private String querySql;
public ColumnInfo(Field field) {
this.field = field;
this.column = AnnotationUtils.findAnnotation(this.field, Column.class);
this.query = AnnotationUtils.findAnnotation(this.field, Query.class);
this.columnName = this.column.name();
this.fieldName = this.field.getName();
this.field.setAccessible(true);
this.querySql = this.getQuerySql(this.query);
}
public String getColumnName() {
return columnName;
}
public String getTemplate() {
return getTemplate(false);
}
public String getTemplate(boolean params) {
if (params) {
return "#{params." + fieldName + "}";
} else {
return "#{" + fieldName + "}";
}
}
public boolean isPrimaryKey() {
return this.column.primaryKey();
}
public boolean fieldIsNotNull(Object entity) {
try {
return this.field.get(entity) != null;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access field for building query conditions.", e);
}
}
public String getQuerySql(Query query) {
if (query == null)
return "";
String column = this.getColumnName();
String iField = getTemplate();
String begin = "#{params." + query.section()[0] + "}";
String end = "#{params." + query.section()[1] + "}";
return switch (query.operation()) {
case eq -> column + " = " + iField;
case ne -> column + " <> " + iField;
case gt -> column + " > " + iField;
case ge -> column + " >= " + iField;
case le -> column + " < " + iField;
case lt -> column + " <= " + iField;
case between -> column + " between " + begin + " and " + end;
case notBetween -> column + " not between " + begin + " and " + end;
case like -> column + " like concat('%'," + iField + ",'%')";
case notLike -> column + "not like concat('%'," + iField + ",'%')";
case likeLeft -> column + "like concat('%'," + iField + ")";
case likeRight -> column + "like concat(" + iField + ",'%')";
case notLikeLeft -> column + "not like concat('%'," + iField + ")";
case notLikeRight -> column + "not like concat(" + iField + ",'%')";
case isNull -> column + " is null";
case isNotNull -> column + " is not null";
case in -> column + " in (" + iField + "";
case notIn -> column + " not in (" + iField + "";
case inSql -> column + " in (" + query.sql() + ")";
case notInSql -> column + " not in (" + query.sql() + ")";
default -> throw new IllegalArgumentException(
"Unsupported operation: " + query.operation());
};
}
public String getQuerySql() {
return this.querySql;
}
}

View File

@ -0,0 +1,93 @@
package com.ruoyi.mybatis.domain;
import java.lang.reflect.Field;
import org.springframework.core.annotation.AnnotationUtils;
import com.ruoyi.mybatis.annotation.ColumnMap;
import com.ruoyi.mybatis.annotation.Query;
public class MapColumnInfo {
private String columnName;
private String fieldName;
private Field field;
private Query query;
private ColumnMap columnMap;
private String querySql;
public MapColumnInfo(Field field) {
this.field = field;
this.columnMap = AnnotationUtils.findAnnotation(this.field, ColumnMap.class);
this.columnName = this.columnMap.name();
this.query = AnnotationUtils.findAnnotation(this.field, Query.class);
this.fieldName = this.field.getName();
this.field.setAccessible(true);
this.querySql = this.getQuerySql(this.query);
}
public ColumnMap getJoin() {
return this.columnMap;
}
public String getColumnName() {
return columnName;
}
public String getTemplate() {
return getTemplate(false);
}
public String getTemplate(boolean params) {
if (params) {
return "#{params." + fieldName + "}";
} else {
return "#{" + fieldName + "}";
}
}
public boolean fieldIsNotNull(Object entity) {
try {
return this.field.get(entity) != null;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access field for building query conditions.", e);
}
}
public String getQuerySql(Query query) {
if (query == null)
return "";
String column = this.getColumnName();
String iField = getTemplate();
String begin = "#{params." + query.section()[0] + "}";
String end = "#{params." + query.section()[1] + "}";
return switch (query.operation()) {
case eq -> column + " = " + iField;
case ne -> column + " <> " + iField;
case gt -> column + " > " + iField;
case ge -> column + " >= " + iField;
case le -> column + " < " + iField;
case lt -> column + " <= " + iField;
case between -> column + " between " + begin + " and " + end;
case notBetween -> column + " not between " + begin + " and " + end;
case like -> column + " like concat('%'," + iField + ",'%')";
case notLike -> column + "not like concat('%'," + iField + ",'%')";
case likeLeft -> column + "like concat('%'," + iField + ")";
case likeRight -> column + "like concat(" + iField + ",'%')";
case notLikeLeft -> column + "not like concat('%'," + iField + ")";
case notLikeRight -> column + "not like concat(" + iField + ",'%')";
case isNull -> column + " is null";
case isNotNull -> column + " is not null";
case in -> column + " in (" + iField + "";
case notIn -> column + " not in (" + iField + "";
case inSql -> column + " in (" + query.sql() + ")";
case notInSql -> column + " not in (" + query.sql() + ")";
default -> throw new IllegalArgumentException(
"Unsupported operation: " + query.operation());
};
}
public String getQuerySql() {
return this.columnMap.target() + "." + this.querySql;
}
}

View File

@ -0,0 +1,124 @@
package com.ruoyi.mybatis.domain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.core.annotation.AnnotationUtils;
import com.ruoyi.mybatis.annotation.Column;
import com.ruoyi.mybatis.annotation.ColumnMap;
import com.ruoyi.mybatis.annotation.EnableTableMap;
import com.ruoyi.mybatis.annotation.Table;
public class TableInfo {
private String tableName;
private EnableTableMap enableTableMap;
private Table table;
private List<ColumnInfo> columns = new ArrayList<>(); // 所有标记column注解的字段
private List<ColumnInfo> primaryKeys = new ArrayList<>();
private List<MapColumnInfo> mapColumns = new ArrayList<>();
private Set<String> joinSql = new HashSet<>();
public TableInfo(Class<?> cls) {
this.table = AnnotationUtils.findAnnotation(cls, Table.class);
if (this.table == null)
throw new RuntimeException("error , not find tableName");
this.tableName = this.table.name();
// 获取所有标记Column注解的字段
this.enableTableMap = AnnotationUtils.findAnnotation(cls, EnableTableMap.class);
Arrays.stream(cls.getDeclaredFields())
.filter(field -> AnnotationUtils.findAnnotation(field, Column.class) != null)
.map(field -> new ColumnInfo(field))
.forEach(this.columns::add);
Arrays.stream(cls.getDeclaredFields())
.filter(field -> AnnotationUtils.findAnnotation(field, ColumnMap.class) != null)
.map(field -> new MapColumnInfo(field))
.forEach(this.mapColumns::add);
this.getColumns().stream()
.filter(ColumnInfo::isPrimaryKey)
.forEach(this.primaryKeys::add);
this.getMapColumns().stream()
.map(MapColumnInfo::getJoin)
.map(join -> join.target() + " on "
+ join.target() + "." + join.targetColumn() + " = "
+ this.getTableNameT() + "." + join.targetColumn())
.forEach(joinSql::add);
}
public Set<String> getJoinSql() {
return this.joinSql;
}
public Boolean isEnbleMap() {
return this.enableTableMap != null;
}
public String getTableNameT() {
return this.enableTableMap.name();
}
public String getTableNameFrom() {
if (this.isEnbleMap())
return this.tableName + " " + this.enableTableMap.name();
else
return this.tableName;
}
public List<String> getQueryColumns() {
List<String> columns = Arrays.asList(this.table.columns());
if (columns.size() <= 0) {
columns = this.columns.stream()
.map(ColumnInfo::getColumnName)
.collect(Collectors.toList());
}
if (this.isEnbleMap()) {
columns = columns.stream()
.map(column -> this.getTableNameT() + "." + column)
.collect(Collectors.toList());
this.mapColumns.stream()
.map(column -> column.getJoin().target() + "." + column.getColumnName())
.forEach(columns::add);
}
return columns;
}
public List<ColumnInfo> getColumns() {
return columns;
}
public List<MapColumnInfo> getMapColumns() {
return mapColumns;
}
public <T> List<ColumnInfo> getNotNullColumns(T entity) {
return this.columns.stream()
.filter(column -> column.fieldIsNotNull(entity))
.collect(Collectors.toList());
}
public <T> List<MapColumnInfo> getNotNullMapColumns(T entity) {
return this.mapColumns.stream()
.filter(column -> column.fieldIsNotNull(entity))
.collect(Collectors.toList());
}
public List<ColumnInfo> getPrimaryKeys() {
return primaryKeys;
}
public String getTableName() {
return tableName;
}
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.mybatis.enums;
public enum QueryEnum {
eq, // 等于 =
ne, // 不等于 <>
gt, // 大于 >
ge, // 大于等于 >=
lt, // 小于 <
le, // 小于等于 <=
like, // 模糊查询
notLike,
likeLeft, // 左模糊查询
likeRight, // 右模糊查询
notLikeLeft,
notLikeRight,
in, // in
notIn, // not in
between, // between and
notBetween, // not between and
isNull, //is null
isNotNull,
inSql,
notInSql;
}

View File

@ -0,0 +1,69 @@
// package com.ruoyi.mybatis.utils;
// import java.util.Arrays;
// import java.util.Map;
// import org.springframework.core.annotation.AnnotationUtils;
// import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// import com.ruoyi.common.core.domain.BaseEntity;
// import com.ruoyi.mybatis.annotation.Query;
// public class QueryWrapperUtil {
// public static <T extends BaseEntity> QueryWrapper<T> initQueryWrapper(T entity) {
// QueryWrapper<T> queryWrapper = new QueryWrapper<>();
// Class<?> clazz = entity.getClass();
// Map<String, Object> params = entity.getParams();
// Arrays.stream(clazz.getDeclaredFields())
// .filter(field -> AnnotationUtils.findAnnotation(field, Query.class) != null)
// .forEach(field -> {
// field.setAccessible(true);
// Query queryAnnotation = field.getAnnotation(Query.class);
// try {
// Object fieldValue = field.get(entity);
// if (fieldValue != null) { // 判断属性值是否非空
// switch (queryAnnotation.operation()) {
// case eq -> queryWrapper.eq(queryAnnotation.column(), fieldValue);
// case ne -> queryWrapper.ne(queryAnnotation.column(), fieldValue);
// case gt -> queryWrapper.gt(queryAnnotation.column(), fieldValue);
// case ge -> queryWrapper.ge(queryAnnotation.column(), fieldValue);
// case le -> queryWrapper.le(queryAnnotation.column(), fieldValue);
// case lt -> queryWrapper.lt(queryAnnotation.column(), fieldValue);
// case between -> {
// String begin = queryAnnotation.section()[0];
// String end = queryAnnotation.section()[1];
// queryWrapper.between(queryAnnotation.column(), params.get(begin), params.get(end));
// }
// case notBetween -> {
// String begin = queryAnnotation.section()[0];
// String end = queryAnnotation.section()[1];
// queryWrapper.notBetween(queryAnnotation.column(), params.get(begin),
// params.get(end));
// }
// case like -> queryWrapper.like(queryAnnotation.column(), fieldValue);
// case notLike -> queryWrapper.notLike(queryAnnotation.column(), fieldValue);
// case likeLeft -> queryWrapper.likeLeft(queryAnnotation.column(), fieldValue);
// case likeRight -> queryWrapper.likeRight(queryAnnotation.column(), fieldValue);
// case notLikeLeft -> queryWrapper.notLikeLeft(queryAnnotation.column(), fieldValue);
// case notLikeRight -> queryWrapper.notLikeRight(queryAnnotation.column(), fieldValue);
// case isNull -> queryWrapper.isNull(queryAnnotation.column());
// case isNotNull -> queryWrapper.isNotNull(queryAnnotation.column());
// case in -> queryWrapper.in(queryAnnotation.column(), (Object[]) fieldValue);
// case notIn -> queryWrapper.notIn(queryAnnotation.column(), (Object[]) fieldValue);
// case inSql -> queryWrapper.inSql(queryAnnotation.column(), queryAnnotation.sql());
// case notInSql -> queryWrapper.notInSql(queryAnnotation.column(), queryAnnotation.sql());
// default ->
// throw new IllegalArgumentException(
// "Unsupported operation: " + queryAnnotation.operation());
// }
// }
// } catch (IllegalAccessException e) {
// throw new RuntimeException("Failed to access field for building query conditions.", e);
// }
// });
// return queryWrapper;
// }
// }

View File

@ -0,0 +1,115 @@
package com.ruoyi.mybatis.utils;
import java.util.ArrayList;
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.mybatis.domain.ColumnInfo;
import com.ruoyi.mybatis.domain.MapColumnInfo;
import com.ruoyi.mybatis.domain.TableInfo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
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.getQueryColumns()))
.FROM(tableInfo.getTableNameFrom());
if (tableInfo.isEnbleMap()) {
tableInfo.getJoinSql().stream()
.forEach(sql::LEFT_OUTER_JOIN);
tableInfo.getNotNullMapColumns(entity).stream()
.map(MapColumnInfo::getQuerySql)
.forEach(sql::WHERE);
tableInfo.getNotNullColumns(entity).stream()
.map(ColumnInfo::getQuerySql)
.map(query -> tableInfo.getTableNameT() + "." + query)
.forEach(sql::WHERE);
} else {
tableInfo.getNotNullColumns(entity).stream()
.map(ColumnInfo::getQuerySql)
.forEach(sql::WHERE);
}
log.debug(sql.toString());
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.getQueryColumns()))
.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();
}
}