diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/ViewObject.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/ViewObject.java new file mode 100644 index 00000000..d258b144 --- /dev/null +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/ViewObject.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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 com.mybatisflex.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * VO(View Object)类。 + * + * @author 王帅 + * @since 2024-04-02 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ViewObject { + + /** + * 对应的 实体类 引用。 + * + * @return 实体类引用 + */ + Class ref(); + + /** + * 是否复制引用类 {@code @Table} 注解上的内容,默认为:{@code true}。 + * + * @return 是否复制属性 + */ + boolean copyTableProps() default true; + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java index ad752e20..fbf0d4dd 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java @@ -15,15 +15,7 @@ */ package com.mybatisflex.core.table; -import com.mybatisflex.annotation.Column; -import com.mybatisflex.annotation.ColumnAlias; -import com.mybatisflex.annotation.ColumnMask; -import com.mybatisflex.annotation.Id; -import com.mybatisflex.annotation.InsertListener; -import com.mybatisflex.annotation.NoneListener; -import com.mybatisflex.annotation.SetListener; -import com.mybatisflex.annotation.Table; -import com.mybatisflex.annotation.UpdateListener; +import com.mybatisflex.annotation.*; import com.mybatisflex.core.BaseMapper; import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.exception.FlexExceptions; @@ -31,53 +23,20 @@ import com.mybatisflex.core.query.QueryChain; import com.mybatisflex.core.query.QueryColumn; import com.mybatisflex.core.query.QueryCondition; import com.mybatisflex.core.query.QueryWrapper; -import com.mybatisflex.core.util.ClassUtil; -import com.mybatisflex.core.util.CollectionUtil; -import com.mybatisflex.core.util.Reflectors; -import com.mybatisflex.core.util.StringUtil; +import com.mybatisflex.core.util.*; import org.apache.ibatis.io.ResolverUtil; import org.apache.ibatis.reflection.Reflector; import org.apache.ibatis.reflection.TypeParameterResolver; -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.TypeException; -import org.apache.ibatis.type.TypeHandler; -import org.apache.ibatis.type.TypeHandlerRegistry; -import org.apache.ibatis.type.UnknownTypeHandler; -import com.mybatisflex.core.util.MapUtil; +import org.apache.ibatis.type.*; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; +import java.lang.reflect.*; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Time; import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Month; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.Year; -import java.time.YearMonth; -import java.time.ZonedDateTime; +import java.time.*; import java.time.chrono.JapaneseDate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -222,7 +181,29 @@ public class TableInfoFactory { // 初始化表名 Table table = entityClass.getAnnotation(Table.class); - if (table != null) { + if (table == null) { + ViewObject vo = entityClass.getAnnotation(ViewObject.class); + if (vo != null) { + TableInfo refTableInfo = ofEntityClass(vo.ref()); + // 设置 VO 类对应的真实的表名 + tableInfo.setSchema(refTableInfo.getSchema()); + tableInfo.setTableName(refTableInfo.getTableName()); + // 将 @Table 注解的属性复制到 VO 类当中 + if (vo.copyTableProps()) { + tableInfo.setComment(refTableInfo.getComment()); + tableInfo.setCamelToUnderline(refTableInfo.isCamelToUnderline()); + tableInfo.setDataSource(refTableInfo.getDataSource()); + + tableInfo.setOnSetListeners(refTableInfo.getOnSetListeners()); + tableInfo.setOnInsertColumns(refTableInfo.getOnInsertColumns()); + tableInfo.setOnUpdateListeners(refTableInfo.getOnUpdateListeners()); + } + } else { + // 默认为类名转驼峰下划线 + String tableName = StringUtil.camelToUnderline(entityClass.getSimpleName()); + tableInfo.setTableName(tableName); + } + } else { tableInfo.setSchema(table.schema()); tableInfo.setTableName(table.value()); tableInfo.setCamelToUnderline(table.camelToUnderline()); @@ -255,10 +236,6 @@ public class TableInfoFactory { if (StringUtil.isNotBlank(table.dataSource())) { tableInfo.setDataSource(table.dataSource()); } - } else { - // 默认为类名转驼峰下划线 - String tableName = StringUtil.camelToUnderline(entityClass.getSimpleName()); - tableInfo.setTableName(tableName); } // 初始化字段相关 diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/DeptVO.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/DeptVO.java new file mode 100644 index 00000000..317a8b9d --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/DeptVO.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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 com.mybatisflex.test.alisa; + +import com.mybatisflex.annotation.ViewObject; + +/** + * 部门。 + * + * @author 王帅 + * @since 2023-11-16 + */ +@ViewObject(ref = SysDept.class) +public class DeptVO extends BaseEntity { + + private Integer id; + private String deptName; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getDeptName() { + return deptName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + + @Override + public String toString() { + return "SysDept{" + + "id=" + id + + ", deptName='" + deptName + '\'' + + '}' + super.toString(); + } + +} diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/RoleVO.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/RoleVO.java new file mode 100644 index 00000000..74bde5c6 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/RoleVO.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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 com.mybatisflex.test.alisa; + +import com.mybatisflex.annotation.ViewObject; + +/** + * 角色。 + * + * @author 王帅 + * @since 2023-11-16 + */ +@ViewObject(ref = SysRole.class) +public class RoleVO extends BaseEntity { + + private Integer id; + private String roleKey; + private String roleName; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRoleKey() { + return roleKey; + } + + public void setRoleKey(String roleKey) { + this.roleKey = roleKey; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + @Override + public String toString() { + return "SysRole{" + + "id=" + id + + ", roleKey='" + roleKey + '\'' + + ", roleName='" + roleName + '\'' + + '}' + super.toString(); + } + +} diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/UserVO.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/UserVO.java new file mode 100644 index 00000000..940eff66 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/alisa/UserVO.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * 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 com.mybatisflex.test.alisa; + +import com.mybatisflex.annotation.ColumnAlias; +import com.mybatisflex.annotation.ViewObject; + +import java.util.Date; +import java.util.List; + +/** + * 用户。 + * + * @author 王帅 + * @since 2023-11-16 + */ +@ViewObject(ref = SysUser.class) +public class UserVO extends BaseEntity { + + private Integer id; + private String userName; + @ColumnAlias("user_age") + private Integer age; + private Date birthday; + + private List roleList; + private List deptList; + + public List getRoleList() { + return roleList; + } + + public void setRoleList(List roleList) { + this.roleList = roleList; + } + + public List getDeptList() { + return deptList; + } + + public void setDeptList(List deptList) { + this.deptList = deptList; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + @Override + public String toString() { + return "SysUser{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", age=" + age + + ", birthday=" + birthday + + ", roleList=" + roleList + + ", deptList=" + deptList + + '}' + super.toString(); + } + +} diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/AlisaTest.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/AlisaTest.java index 6fb7b503..2f7be3ef 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/AlisaTest.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/AlisaTest.java @@ -16,10 +16,13 @@ package com.mybatisflex.test.mapper; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.test.alisa.SysUser; +import com.mybatisflex.test.alisa.UserVO; import org.apache.ibatis.mapping.ResultMap; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -63,7 +66,7 @@ class AlisaTest { .select(SYS_USER.DEFAULT_COLUMNS) .select(SYS_ROLE.DEFAULT_COLUMNS) .from(SYS_USER.as("u")) - .leftJoin(SYS_ROLE).as("r").on(SYS_USER.ID.eq(1)); + .leftJoin(SYS_ROLE.as("r")).on(SYS_USER.ID.eq(1)); printList(queryWrapper); } @@ -75,8 +78,8 @@ class AlisaTest { .select(SYS_ROLE.DEFAULT_COLUMNS) .select(SYS_DEPT.DEFAULT_COLUMNS) .from(SYS_USER.as("u")) - .leftJoin(SYS_ROLE).as("r").on(SYS_USER.ID.eq(1)) - .leftJoin(SYS_DEPT).as("d").on(SYS_USER.ID.eq(1)); + .leftJoin(SYS_ROLE.as("r")).on(SYS_USER.ID.eq(1)) + .leftJoin(SYS_DEPT.as("d")).on(SYS_USER.ID.eq(1)); printList(queryWrapper); } @@ -89,8 +92,8 @@ class AlisaTest { .select(SYS_DEPT.DEFAULT_COLUMNS) .select(SYS_USER.DEFAULT_COLUMNS) .from(SYS_USER.as("u")) - .leftJoin(SYS_ROLE).as("r").on(SYS_USER.ID.eq(1)) - .leftJoin(SYS_DEPT).as("d").on(SYS_USER.ID.eq(1)); + .leftJoin(SYS_ROLE.as("r")).on(SYS_USER.ID.eq(1)) + .leftJoin(SYS_DEPT.as("d")).on(SYS_USER.ID.eq(1)); printList(queryWrapper); } @@ -126,7 +129,7 @@ class AlisaTest { .select(SYS_USER.ID, SYS_USER.USER_NAME, SYS_USER.AGE, SYS_USER.BIRTHDAY) .select(SYS_ROLE.CREATE_BY.as("sys_role$create_by")) .from(SYS_USER.as("u")) - .leftJoin(SYS_ROLE).as("r").on(SYS_USER.ID.eq(1)); + .leftJoin(SYS_ROLE.as("r")).on(SYS_USER.ID.eq(1)); Object[] objects = FlexGlobalConfig.getDefaultConfig() .getConfiguration() @@ -145,4 +148,22 @@ class AlisaTest { printList(queryWrapper); } + @Test + void test07() throws JsonProcessingException { + QueryWrapper queryWrapper = QueryWrapper.create() + .select(SYS_USER.DEFAULT_COLUMNS) + .select(SYS_ROLE.DEFAULT_COLUMNS) + .select(SYS_DEPT.DEFAULT_COLUMNS) + .from(SYS_USER.as("u")) + .leftJoin(SYS_ROLE.as("r")).on(SYS_USER.ID.eq(1)) + .leftJoin(SYS_DEPT.as("d")).on(SYS_USER.ID.eq(1)); + + ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter(); + + String userList1 = objectWriter.writeValueAsString(userMapper.selectListByQuery(queryWrapper)); + String userList2 = objectWriter.writeValueAsString(userMapper.selectListByQueryAs(queryWrapper, UserVO.class)); + + Assertions.assertEquals(userList1, userList2); + } + }