feature: 根据注解获取排序列的tableName别名or默认排序
This commit is contained in:
parent
4db3e90872
commit
4cc0408f73
14
pom.xml
14
pom.xml
|
|
@ -40,12 +40,24 @@
|
||||||
<common-pool.version>2.10.0</common-pool.version>
|
<common-pool.version>2.10.0</common-pool.version>
|
||||||
<commons-collections.version>3.2.2</commons-collections.version>
|
<commons-collections.version>3.2.2</commons-collections.version>
|
||||||
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
|
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
|
||||||
|
<mockito.version>4.1.0</mockito.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<!-- SpringCloud 微服务 -->
|
<!-- SpringCloud 微服务 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,22 @@
|
||||||
<groupId>io.swagger</groupId>
|
<groupId>io.swagger</groupId>
|
||||||
<artifactId>swagger-annotations</artifactId>
|
<artifactId>swagger-annotations</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.ruoyi.common.core.annotation.order;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义排序
|
||||||
|
* 如何使用:
|
||||||
|
* @DefaultOrder(column="createTime", orderType="desc", tableName="user")
|
||||||
|
* class UserVO {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* startPage(UserVO.class)
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Repeatable(CustomOrders.class)
|
||||||
|
public @interface CustomOrder {
|
||||||
|
// 列名 驼峰最终会转换为下划线命名法作为最终排序列名。
|
||||||
|
String column() default "";
|
||||||
|
|
||||||
|
// 列对应的表名
|
||||||
|
String tableName() default "";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.ruoyi.common.core.annotation.order;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义排序组合注解
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Component
|
||||||
|
public @interface CustomOrders {
|
||||||
|
CustomOrder[] value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.ruoyi.common.core.annotation.order;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认排序
|
||||||
|
* 如何使用:
|
||||||
|
* @DefaultOrder(column="createTime", orderType="desc", tableName="user")
|
||||||
|
* class UserVO {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* startPage(UserVO.class)
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface DefaultOrder {
|
||||||
|
// 默认排序列 驼峰最终会转换为下划线命名法作为最终排序列名。
|
||||||
|
String column() default "";
|
||||||
|
// 排序类型, desc/asc
|
||||||
|
String orderType() default "asc";
|
||||||
|
// 表名, 可不指定
|
||||||
|
String tableName() default "";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.ruoyi.common.core.annotation.order;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段表别名
|
||||||
|
* 如何使用:
|
||||||
|
* class UserVO {
|
||||||
|
* ...
|
||||||
|
* @TableAlias("dept")
|
||||||
|
* private String deptName;
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* startPage(UserVO.class)
|
||||||
|
* 查询多表关联时, 指定表别名, 即可简单实现完成对应的字段排序。
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface TableAlias {
|
||||||
|
String value() default "";
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
package com.ruoyi.common.core.web.controller;
|
package com.ruoyi.common.core.web.controller;
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.annotation.order.CustomOrder;
|
||||||
|
import com.ruoyi.common.core.annotation.order.DefaultOrder;
|
||||||
|
import com.ruoyi.common.core.annotation.order.TableAlias;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
|
|
@ -60,12 +66,162 @@ public class BaseController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求分页数据
|
||||||
|
* 并根据class的注解设置排序列
|
||||||
|
* 列对应表名优先级
|
||||||
|
* TableAlias > CustomOrder > DefaultOrder
|
||||||
|
* @param clazz
|
||||||
|
*/
|
||||||
|
protected void startPage(Class<?> clazz) {
|
||||||
|
// 正常分页的情况
|
||||||
|
if (clazz == null) {
|
||||||
|
startPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||||
|
Integer pageNum = pageDomain.getPageNum();
|
||||||
|
Integer pageSize = pageDomain.getPageSize();
|
||||||
|
if (pageNum != null && pageSize != null) {
|
||||||
|
PageHelper.startPage(pageNum, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理orderBy的情况。
|
||||||
|
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
|
||||||
|
String column = SqlUtil.escapeOrderBySql(pageDomain.getOrderByColumn());
|
||||||
|
// 获取默认排序
|
||||||
|
if (StringUtils.isEmpty(orderBy)) {
|
||||||
|
orderBy = getDefaultOrderByAnnotation(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(orderBy)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 根据列获取表名
|
||||||
|
String tableName = getTableNameByColumn(clazz, column);
|
||||||
|
if (StringUtils.isNotEmpty(tableName)) {
|
||||||
|
orderBy = tableName + "." + orderBy;
|
||||||
|
}
|
||||||
|
PageHelper.orderBy(orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试从field的TableAlias获取表别名
|
||||||
|
* @param clazz
|
||||||
|
* @param column
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getFieldTableName(Class<?> clazz, String column) {
|
||||||
|
// 获取对象中所有的成员变量
|
||||||
|
Field[] declaredFields = clazz.getDeclaredFields();
|
||||||
|
for (Field field : declaredFields) {
|
||||||
|
String fieldName = field.getName();
|
||||||
|
if (Objects.equals(column, fieldName)) {
|
||||||
|
if (field.isAnnotationPresent(TableAlias.class)) {
|
||||||
|
TableAlias orderTableAlias = field.getAnnotation(TableAlias.class);
|
||||||
|
return orderTableAlias.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试从CustomOrder获取表别名
|
||||||
|
* @param clazz
|
||||||
|
* @param column
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getCustomOrderTableName(Class<?> clazz, String column) {
|
||||||
|
// 获取对象中所有的成员变量
|
||||||
|
if (clazz.isAnnotationPresent(CustomOrder.class)) {
|
||||||
|
CustomOrder[] customOrders = clazz.getAnnotationsByType(CustomOrder.class);
|
||||||
|
for (CustomOrder customOrder : customOrders) {
|
||||||
|
String realColumn = column;
|
||||||
|
if (column.contains("_")) {
|
||||||
|
realColumn = StringUtils.toCamelCase(customOrder.column());
|
||||||
|
}
|
||||||
|
if (Objects.equals(column, realColumn)) {
|
||||||
|
return customOrder.tableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取默认排序
|
||||||
|
* @param clazz
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getDefaultTableName(Class<?> clazz) {
|
||||||
|
// 最后,查找类上的tableName
|
||||||
|
if (clazz.isAnnotationPresent(DefaultOrder.class)) {
|
||||||
|
DefaultOrder defaultOrder = clazz.getAnnotation(DefaultOrder.class);
|
||||||
|
if (StringUtils.isNotEmpty(defaultOrder.tableName())) {
|
||||||
|
return defaultOrder.tableName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过过滤列获取对应的table
|
||||||
|
* @param clazz
|
||||||
|
* @param column
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getTableNameByColumn(Class<?> clazz, String column) {
|
||||||
|
if (clazz == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String tableName = null;
|
||||||
|
// 未指定排序 则尝试设置默认排序的Table
|
||||||
|
if (StringUtils.isEmpty(column)) {
|
||||||
|
tableName = getDefaultTableName(clazz);
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 优先获取字段的tableName
|
||||||
|
tableName = getFieldTableName(clazz, column);
|
||||||
|
if (StringUtils.isNotEmpty(tableName)) {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其次查找CustomOrder定义的column对应的TableName
|
||||||
|
tableName = getCustomOrderTableName(clazz, column);
|
||||||
|
if (StringUtils.isNotEmpty(tableName)) {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取默认排序
|
||||||
|
tableName = getDefaultTableName(clazz);
|
||||||
|
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类注解获取默认过滤列
|
||||||
|
* @param clazz
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getDefaultOrderByAnnotation(Class<?> clazz) {
|
||||||
|
if (!clazz.isAnnotationPresent(DefaultOrder.class)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DefaultOrder defaultOrder = clazz.getAnnotation(DefaultOrder.class);
|
||||||
|
String orderBy = null;
|
||||||
|
if (StringUtils.isNotEmpty(defaultOrder.column())) {
|
||||||
|
orderBy = StringUtils.toUnderScoreCase(defaultOrder.column()) + " " + defaultOrder.orderType();
|
||||||
|
}
|
||||||
|
return orderBy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 响应请求分页数据
|
* 响应请求分页数据
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
protected TableDataInfo getDataTable(List<?> list)
|
protected TableDataInfo getDataTable(List<?> list) {
|
||||||
{
|
|
||||||
TableDataInfo rspData = new TableDataInfo();
|
TableDataInfo rspData = new TableDataInfo();
|
||||||
rspData.setCode(HttpStatus.SUCCESS);
|
rspData.setCode(HttpStatus.SUCCESS);
|
||||||
rspData.setRows(list);
|
rspData.setRows(list);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
package com.ruoyi.common.core.web.controller;
|
||||||
|
|
||||||
|
import com.github.pagehelper.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.ruoyi.common.core.annotation.order.CustomOrder;
|
||||||
|
import com.ruoyi.common.core.annotation.order.DefaultOrder;
|
||||||
|
import com.ruoyi.common.core.annotation.order.TableAlias;
|
||||||
|
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.web.page.PageDomain;
|
||||||
|
import com.ruoyi.common.core.web.page.TableSupport;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.MockedStatic;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class BaseControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testStartPageByDefaultOrder()
|
||||||
|
{
|
||||||
|
@DefaultOrder(tableName = "user", column = "userName")
|
||||||
|
class UserVO {
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(10);
|
||||||
|
pageDomain.setPageSize(20);
|
||||||
|
|
||||||
|
MockedStatic<TableSupport> mocked = Mockito.mockStatic(TableSupport.class);
|
||||||
|
mocked.when(TableSupport::buildPageRequest).thenReturn(
|
||||||
|
pageDomain
|
||||||
|
);
|
||||||
|
new BaseController().startPage(UserVO.class);
|
||||||
|
Page<Object> localPage = PageHelper.getLocalPage();
|
||||||
|
String orderBy = localPage.getOrderBy();
|
||||||
|
assertEquals("user.user_name asc", orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testStartPageByDefaultOrder2()
|
||||||
|
{
|
||||||
|
@DefaultOrder(tableName = "user", column = "user_name")
|
||||||
|
class UserVO {
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(10);
|
||||||
|
pageDomain.setPageSize(20);
|
||||||
|
|
||||||
|
MockedStatic<TableSupport> mocked = Mockito.mockStatic(TableSupport.class);
|
||||||
|
mocked.when(TableSupport::buildPageRequest).thenReturn(
|
||||||
|
pageDomain
|
||||||
|
);
|
||||||
|
new BaseController().startPage(UserVO.class);
|
||||||
|
Page<Object> localPage = PageHelper.getLocalPage();
|
||||||
|
String orderBy = localPage.getOrderBy();
|
||||||
|
assertEquals("user.user_name asc", orderBy);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void testStartPageByTableAlias()
|
||||||
|
{
|
||||||
|
class UserVO {
|
||||||
|
@TableAlias("user")
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(10);
|
||||||
|
pageDomain.setPageSize(20);
|
||||||
|
pageDomain.setOrderByColumn("userName");
|
||||||
|
MockedStatic<TableSupport> mocked = Mockito.mockStatic(TableSupport.class);
|
||||||
|
mocked.when(TableSupport::buildPageRequest).thenReturn(
|
||||||
|
pageDomain
|
||||||
|
);
|
||||||
|
new BaseController().startPage(UserVO.class);
|
||||||
|
Page<Object> localPage = PageHelper.getLocalPage();
|
||||||
|
String orderBy = localPage.getOrderBy();
|
||||||
|
assertEquals("user.user_name asc", orderBy);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void testStartPageByCustomOrder()
|
||||||
|
{
|
||||||
|
@CustomOrder(tableName = "user", column = "createTime")
|
||||||
|
class UserVO extends BaseEntity {
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(10);
|
||||||
|
pageDomain.setPageSize(20);
|
||||||
|
pageDomain.setOrderByColumn("createTime");
|
||||||
|
pageDomain.setIsAsc("desc");
|
||||||
|
|
||||||
|
MockedStatic<TableSupport> mocked = Mockito.mockStatic(TableSupport.class);
|
||||||
|
mocked.when(TableSupport::buildPageRequest).thenReturn(
|
||||||
|
pageDomain
|
||||||
|
);
|
||||||
|
new BaseController().startPage(UserVO.class);
|
||||||
|
Page<Object> localPage = PageHelper.getLocalPage();
|
||||||
|
String orderBy = localPage.getOrderBy();
|
||||||
|
assertEquals("user.create_time desc", orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testStartPageByCustomOrder2()
|
||||||
|
{
|
||||||
|
@CustomOrder(tableName = "user", column = "create_time")
|
||||||
|
class UserVO extends BaseEntity {
|
||||||
|
private String userName;
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(10);
|
||||||
|
pageDomain.setPageSize(20);
|
||||||
|
pageDomain.setOrderByColumn("createTime");
|
||||||
|
pageDomain.setIsAsc("desc");
|
||||||
|
|
||||||
|
MockedStatic<TableSupport> mocked = Mockito.mockStatic(TableSupport.class);
|
||||||
|
mocked.when(TableSupport::buildPageRequest).thenReturn(
|
||||||
|
pageDomain
|
||||||
|
);
|
||||||
|
new BaseController().startPage(UserVO.class);
|
||||||
|
Page<Object> localPage = PageHelper.getLocalPage();
|
||||||
|
String orderBy = localPage.getOrderBy();
|
||||||
|
assertEquals("user.create_time desc", orderBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue