diff --git a/README.md b/README.md
index c03e9c8ec8fb42569f041c147e164d4a8434e953..ff6e4c63557ebefa5e4d324581f5e0600cdc0613 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ https://search.maven.org/artifact/com.gitee.qdbp/qdbp-jdbc-spring
com.gitee.qdbp
qdbp-jdbc-spring
- 4.1.5
+ 4.1.8
```
如果不是spring-web项目,可以单独使用qdbp-jdbc-core
@@ -61,6 +61,14 @@ https://search.maven.org/artifact/com.gitee.qdbp/qdbp-jdbc-core
com.gitee.qdbp
qdbp-jdbc-core
- 4.1.5
+ 4.1.8
+
+```
+如果是jdk8以上版本,存在LocalDateTime的转换问题,需要引入qdbp-jdbc-jdk8
+```xml
+
+ com.gitee.qdbp
+ qdbp-jdbc-jdk8
+ 4.1.8
```
diff --git a/jdbc-core/pom.xml b/jdbc-core/pom.xml
index a1b138fb7ec441cd0b15eeb539808d8713925692..5c3b20cf14503ba0f6692198f70c1f1372004a91 100644
--- a/jdbc-core/pom.xml
+++ b/jdbc-core/pom.xml
@@ -9,7 +9,7 @@
qdbp-jdbc-core
- 4.1.5
+ 4.1.8
jar
${project.artifactId}
https://gitee.com/qdbp/qdbp-jdbc/
@@ -25,12 +25,12 @@
com.gitee.qdbp
qdbp-able
- 5.4.5
+ 5.4.6
com.gitee.qdbp
qdbp-staticize
- 3.5.3
+ 3.5.5
com.gitee.qdbp
diff --git a/jdbc-core/src/main/java/com/gitee/qdbp/filling/api/EntityFillType.java b/jdbc-core/src/main/java/com/gitee/qdbp/filling/api/EntityFillType.java
index 649c68272ae9f721fb06dd9bd33af65b67e431c1..e95b3d2392d81c9455aecc6ce50561b10e470664 100644
--- a/jdbc-core/src/main/java/com/gitee/qdbp/filling/api/EntityFillType.java
+++ b/jdbc-core/src/main/java/com/gitee/qdbp/filling/api/EntityFillType.java
@@ -15,5 +15,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityFillType {
+ /** 规则名称 **/
String[] value();
}
diff --git a/jdbc-core/src/main/java/com/gitee/qdbp/filling/biz/BaseEntityDataFillFieldValueBasic.java b/jdbc-core/src/main/java/com/gitee/qdbp/filling/biz/BaseEntityDataFillFieldValueBasic.java
new file mode 100644
index 0000000000000000000000000000000000000000..05d7998b875a4a7ab71602f04f35796f18a3726e
--- /dev/null
+++ b/jdbc-core/src/main/java/com/gitee/qdbp/filling/biz/BaseEntityDataFillFieldValueBasic.java
@@ -0,0 +1,201 @@
+package com.gitee.qdbp.filling.biz;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.gitee.qdbp.able.beans.KeyString;
+import com.gitee.qdbp.able.beans.KeyValue;
+import com.gitee.qdbp.filling.api.EntityDataTypedFillService;
+import com.gitee.qdbp.tools.utils.ConvertTools;
+import com.gitee.qdbp.tools.utils.NamingTools;
+import com.gitee.qdbp.tools.utils.StringTools;
+import com.gitee.qdbp.tools.utils.VerifyTools;
+
+/**
+ * 实体数据填充单一类型处理基础实现类
+ *
+ * @author zhaohuihua
+ * @version 20210113
+ */
+public abstract class BaseEntityDataFillFieldValueBasic implements EntityDataTypedFillService {
+
+ protected boolean skipDataFill(Map data) {
+ return false;
+ }
+
+ protected boolean skipSourceValue(Serializable sourceValue) {
+ return false;
+ }
+
+ // originalData: key=sourceValue
+ // valueMaps: key=sourceValue, value=targetValue
+ protected void fillValueToOriginalData(Map extends Serializable, List> originalData, Map, ?> valueMaps) {
+ // # 将targetValue填充至originalData
+ for (Map.Entry extends Serializable, List> entry : originalData.entrySet()) {
+ Serializable sourceValue = entry.getKey();
+ if (valueMaps.containsKey(sourceValue)) {
+ Object targetValue = valueMaps.get(sourceValue);
+ List fillors = entry.getValue();
+ for (DataFillor fillor : fillors) {
+ fillor.fillValues(targetValue);
+ }
+ }
+ }
+ }
+
+ /**
+ * options多个字段以逗号分隔, 默认的填充字段为源字段去掉Id/Code后缀, 加上Name
+ * -- createUser,updateUser
+ * -- 等于createUser-createUserName,updateUser-updateUserName
+ * 也可以自定义转换关系
+ * -- creatorId-createUser,updatorId-updateUser
+ * @param options 转换规则
+ * @return 解析后的规则, key=fieldName, value=targetName
+ */
+ protected List parseOptions(String options) {
+ List list = new ArrayList<>();
+ if (options == null || options.trim().length() == 0) {
+ return list;
+ }
+ String[] array = StringTools.split(options, ',');
+ for (String option : array) {
+ option = option.trim();
+ int index = option.indexOf('-');
+ if (index < 0) {
+ list.add(new KeyString(option, convertToTargetName(option)));
+ } else if (index > 0) {
+ String source = option.substring(0, index).trim();
+ String target = option.substring(index + 1).trim();
+ list.add(new KeyString(source, target));
+ // } else {
+ // 横框开头? 忽略!
+ }
+ }
+ return list;
+ }
+
+ protected Map extends Serializable, List> collectFillInfos(Iterable
+
+ com.gitee.qdbp
+ qdbp-jdbc-jdk8
+ ${project.version}
+
com.gitee.qdbp
qdbp-tools
- 5.4.5
+ 5.4.6
@@ -236,6 +245,7 @@
org.apache.maven.plugins
maven-surefire-plugin
+ 2.12.4
src/test/resources/testng.xml
diff --git a/jdbc-test/src/main/resources/settings/qdbc/qdbc.taglib.txt b/jdbc-test/src/main/resources/settings/qdbc/qdbc.taglib.txt
index 1b4ca7ab40a6a4197ba45d7de3f2ee151948f09a..863260cf7e025026ddec6b3ec728f0107b5ebf4c 100644
--- a/jdbc-test/src/main/resources/settings/qdbc/qdbc.taglib.txt
+++ b/jdbc-test/src/main/resources/settings/qdbc/qdbc.taglib.txt
@@ -10,10 +10,14 @@ when = com.gitee.qdbp.staticize.tags.core.WhenTag
otherwise = com.gitee.qdbp.staticize.tags.core.OtherwiseTag
comment = com.gitee.qdbp.staticize.tags.core.CommentTag
define = com.gitee.qdbp.staticize.tags.core.SetVariableTag
+out = com.gitee.qdbp.staticize.tags.core.OutTag
+property = com.gitee.qdbp.staticize.tags.core.SetVariableTag
+config = com.gitee.qdbp.jdbc.tags.ConfigValueTag
foreach = com.gitee.qdbp.jdbc.tags.SqlForEachTag
include = com.gitee.qdbp.jdbc.tags.IncludeTag
sql:include = com.gitee.qdbp.jdbc.tags.IncludeTag
+property = com.gitee.qdbp.jdbc.tags.PropertyTag
append = com.gitee.qdbp.jdbc.tags.AppendTag
sql-append = com.gitee.qdbp.jdbc.tags.AppendTag
sql:append = com.gitee.qdbp.jdbc.tags.AppendTag
@@ -48,7 +52,7 @@ fmt-date = com.gitee.qdbp.staticize.tags.core.DateFormatTag
fmt:date = com.gitee.qdbp.staticize.tags.core.DateFormatTag
# 指定值栈包装类, 用于实现在业务侧自定义值栈自身的函数
-@StackWrapper = com.gitee.qdbp.staticize.common.StackWrapper
+@StackWrapper = com.gitee.qdbp.able.model.reusable.StackWrapper
# 全局静态类, 最常用的在这里指定, 省去
@DateTools = com.gitee.qdbp.tools.utils.DateTools
diff --git a/jdbc-core/src/main/resources/settings/sqls/GlobalRecursive.sql b/jdbc-test/src/main/resources/settings/sqls/GlobalRecursive2.sql
similarity index 92%
rename from jdbc-core/src/main/resources/settings/sqls/GlobalRecursive.sql
rename to jdbc-test/src/main/resources/settings/sqls/GlobalRecursive2.sql
index 582b0c1997672ca67dbafc3962274ae1373b61a0..8b5b559b44846e20cd31f20f0c22f85baf9bf7dc 100644
--- a/jdbc-core/src/main/resources/settings/sqls/GlobalRecursive.sql
+++ b/jdbc-test/src/main/resources/settings/sqls/GlobalRecursive2.sql
@@ -9,7 +9,7 @@
-- <> 递归查询所有子节点, 标准递归语法
-- mysql.8,mariadb.10.2.2,postgresql,db2,h2,sqlserver,sqlite.3.8.3
-${db.config.get('recursive.keyword')} recursive_temp_table(temp_parent) AS (
+ recursive_temp_table(temp_parent) AS (
SELECT ${codeColumn} temp_parent FROM ${tableName}
WHERE
#{filterWhere}
@@ -27,7 +27,7 @@ WHERE ${codeColumn} IN ( SELECT temp_parent FROM recursive_temp_table )
-- <> 递归查询所有子节点, mysql专用递归语法
/*-- 可能需要调整GROUP_CONCAT的长度: group_concat_max_len = 40960 --*/
-SELECT ${selectColumns} FROM (
+SELECT DISTINCT ${selectColumns} FROM (
SELECT T.ID__LIST FROM (
SELECT @IDS AS ID__LIST, (
SELECT @IDS := GROUP_CONCAT( ${codeColumn} )
@@ -45,14 +45,14 @@ WHERE FIND_IN_SET( T2.${codeColumn}, T1.ID__LIST )
-- <> 递归查询所有子节点, oracle专用递归语法
-SELECT ${selectColumns} FROM (
+SELECT DISTINCT ${selectColumns} FROM (
SELECT * FROM ${tableName}
START WITH
CONNECT BY PRIOR ${codeColumn}=${parentColumn}
#{filterWhere}
+ #{orderBy}
)
#{searchWhere}
-#{orderBy}
-- <> 递归查询所有子节点, 使用存储过程实现的递归查询
@@ -71,7 +71,7 @@ CALL RECURSIVE_LIST_CHILDREN_QUERY (
-- <> 递归查询所有父节点, 标准递归语法
-- mysql.8,mariadb.10.2.2,postgresql,db2,h2,sqlserver,sqlite.3.8.3
-${db.config.get('recursive.keyword')} recursive_temp_table(temp_parent) AS (
+ recursive_temp_table(temp_parent) AS (
SELECT ${codeColumn} temp_parent FROM ${tableName}
WHERE
#{filterWhere}
@@ -89,7 +89,7 @@ WHERE ${codeColumn} IN ( SELECT temp_parent FROM recursive_temp_table )
-- <> 递归查询所有父节点, mysql专用递归语法
/*-- 可能需要调整GROUP_CONCAT的长度: group_concat_max_len = 40960 --*/
-SELECT ${selectColumns} FROM (
+SELECT DISTINCT ${selectColumns} FROM (
SELECT T.ID__LIST FROM (
SELECT @IDS AS ID__LIST, (
SELECT @IDS := GROUP_CONCAT(${parentColumn})
@@ -107,14 +107,14 @@ WHERE FIND_IN_SET( T2.${codeColumn}, T1.ID__LIST )
-- <> 递归查询所有父节点, oracle专用递归语法
-SELECT ${selectColumns} FROM (
+SELECT DISTINCT ${selectColumns} FROM (
SELECT * FROM ${tableName}
START WITH
CONNECT BY PRIOR ${parentColumn}=${codeColumn}
#{filterWhere}
+ #{orderBy}
)
#{searchWhere}
-#{orderBy}
-- <> 递归查询所有父节点, 使用存储过程实现的递归查询
diff --git a/jdbc-test/src/main/resources/settings/sqls/SqlIncludeTagTest.xml b/jdbc-test/src/main/resources/settings/sqls/SqlIncludeTagTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..102721610f207d4b088b95af8c55c79247b288ef
--- /dev/null
+++ b/jdbc-test/src/main/resources/settings/sqls/SqlIncludeTagTest.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
diff --git a/jdbc-test/src/main/resources/settings/sqls/select.001.sql b/jdbc-test/src/main/resources/settings/sqls/select.001.sql
index 0afd1bfc5f6d97a92df06a5d49744ef7ba82ea8f..df62b4e91aea8296eb7fd48f5e8361d978f508d2 100644
--- a/jdbc-test/src/main/resources/settings/sqls/select.001.sql
+++ b/jdbc-test/src/main/resources/settings/sqls/select.001.sql
@@ -16,3 +16,11 @@ AND r.DATA_STATE=1
WHERE ur.DATA_STATE=1
AND ur.USER_ID IN ( #{userIds} )
+-- << user.roles.query8 >> 查询用户有哪些角色
+SELECT * FROM TEST_USER_ROLE_REF ur
+INNER JOIN TEST_ROLE_CORE_INFO r
+ON ur.ROLE_ID=r.ID
+AND r.DATA_STATE=1
+WHERE ur.DATA_STATE=1
+AND ur.USER_ID IN ( #{userIds} )
+
diff --git a/jdbc-test/src/main/resources/settings/sqls/select.002.sql b/jdbc-test/src/main/resources/settings/sqls/select.002.sql
index 4ef1440824daea89940d64984891948510dc5424..3f54953e22353d23fe7c0a1d18467d2232ce46d2 100644
--- a/jdbc-test/src/main/resources/settings/sqls/select.002.sql
+++ b/jdbc-test/src/main/resources/settings/sqls/select.002.sql
@@ -15,3 +15,11 @@ ON ur.ROLE_ID=r.ID
AND r.DATA_STATE=1
WHERE ur.DATA_STATE=1
AND ur.USER_ID IN ( #{userIds} )
+
+-- << user.roles.query8 >> 查询用户有哪些角色
+SELECT * FROM TEST_USER_ROLE_REF ur
+INNER JOIN TEST_ROLE_CORE_INFO r
+ON ur.ROLE_ID=r.ID
+AND r.DATA_STATE=1
+WHERE ur.DATA_STATE=1
+AND ur.USER_ID IN ( #{userIds} )
diff --git a/jdbc-test/src/main/resources/settings/sqls/select.003.sql b/jdbc-test/src/main/resources/settings/sqls/select.003.sql
index 079d30e748e6a69b4a2d4264471648feff8f4214..57cd82ba22e563c550baf915d74c5f899155f978 100644
--- a/jdbc-test/src/main/resources/settings/sqls/select.003.sql
+++ b/jdbc-test/src/main/resources/settings/sqls/select.003.sql
@@ -42,3 +42,13 @@ ON ur.ROLE_ID=r.ID
AND r.DATA_STATE=1
WHERE ur.DATA_STATE=1
AND ur.USER_ID IN ( #{userIds} )
+
+
+-- << user.roles.query8:200 >> 查询用户有哪些角色
+SELECT * FROM TEST_USER_ROLE_REF ur
+INNER JOIN TEST_ROLE_CORE_INFO r
+ON ur.ROLE_ID=r.ID
+AND r.DATA_STATE=1
+WHERE ur.DATA_STATE=1
+AND ur.USER_ID IN ( #{userIds} )
+AND r.TENANT_CODE='000000'
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/ConvertErrorTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/ConvertErrorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b086d6412d18f0d4a6fa7f63516e007aafe43c7
--- /dev/null
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/ConvertErrorTest.java
@@ -0,0 +1,376 @@
+package com.gitee.qdbp.jdbc.test.biz;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Table;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import com.gitee.qdbp.able.exception.ServiceException;
+import com.gitee.qdbp.able.jdbc.condition.DbWhere;
+import com.gitee.qdbp.jdbc.api.CrudDao;
+import com.gitee.qdbp.jdbc.api.QdbcBoot;
+import com.gitee.qdbp.jdbc.exception.DbErrorCode;
+import com.gitee.qdbp.jdbc.test.base.CommEntity;
+import com.gitee.qdbp.jdbc.test.enums.AccountType;
+import com.gitee.qdbp.jdbc.test.enums.Gender;
+import com.gitee.qdbp.jdbc.test.enums.UserSource;
+import com.gitee.qdbp.jdbc.test.enums.UserState;
+import com.gitee.qdbp.jdbc.test.enums.UserType;
+import com.gitee.qdbp.jdbc.test.model.SysUserEntity;
+import com.gitee.qdbp.jdbc.test.model.UserCoreOptions;
+import com.gitee.qdbp.tools.utils.DateTools;
+import com.gitee.qdbp.tools.utils.JsonTools;
+
+/**
+ * ConvertErrorTest
+ *
+ * @author zhaohuihua
+ * @version 20211004
+ */
+@Test
+@ContextConfiguration(locations = {"classpath:settings/spring/spring.xml"})
+public class ConvertErrorTest extends AbstractTestNGSpringContextTests {
+
+ private static final Logger log = LoggerFactory.getLogger(com.gitee.qdbp.jdbc.test.biz.SimpleCrudDaoTest.class);
+
+ private static final String TACD = "ConvertError";
+ @Autowired
+ private QdbcBoot qdbcBoot;
+
+ @Test(priority = 1001)
+ public void testUserEntityDelete() {
+ DbWhere where = new DbWhere();
+ where.on("tenantCode").equals(TACD);
+ CrudDao dao = qdbcBoot.crudDao(SysUserEntity.class);
+ dao.physicalDelete(where);
+ }
+
+ @Test(priority = 1003)
+ public void testUserEntityCreate() {
+ CrudDao dao = qdbcBoot.crudDao(SysUserEntity.class);
+ SysUserEntity entity = new SysUserEntity();
+ entity.setTenantCode(TACD);
+ entity.setUserCode("super");
+ entity.setSuperman(true);
+ entity.setDeptId("0");
+ entity.setCity("beijing");
+ entity.setGender(Gender.UNKNOWN);
+ entity.setBirthday(DateTools.parse("2018-02-03 15:25:35.456"));
+ entity.setUserState(UserState.NORMAL);
+ entity.setUserSource(UserSource.INPUT);
+ entity.setCreateTime(DateTools.parse("2018-05-15 20:30:40.599"));
+
+ entity.setId("ConvertError001");
+ entity.setUserType(UserType.ADMIN);
+ dao.insert(entity);
+ }
+
+ @Test(priority = 2011)
+ public void testUserEntityQuery() {
+ try {
+ TestUserEntity user = qdbcBoot.crudStream(TestUserEntity.class)
+ .where("tenantCode").equals(TACD)
+ .and("id").equals("ConvertError001")
+ .end()
+ .find();
+ log.debug("UserEntityQueryResult: {}", JsonTools.toLogString(user));
+ } catch (ServiceException e) {
+ log.error("UserEntityQueryError", e);
+ Assert.assertEquals(e.getCode(), DbErrorCode.DB_COLUMN_VALUE_ERROR.getCode());
+ Assert.assertTrue(e.getDetails().contains("TestUserEntity.city"));
+ }
+ }
+
+ @Table(name = "TEST_USER_CORE_INFO")
+ public static class TestUserEntity extends CommEntity {
+
+ /** 版本序列号 **/
+ private static final long serialVersionUID = 1L;
+
+ /** 租户编号 **/
+ @Column
+ private String tenantCode;
+ /** 用户类型 **/
+ @Column
+ private AccountType userType;
+ /** 部门ID **/
+ @Column
+ private String deptId;
+ /** 账号/工号 **/
+ @Column
+ private String userCode;
+ /** 登录用户名 **/
+ @Column
+ private String userName;
+ /** 昵称 **/
+ @Column
+ private String nickName;
+ /** 真实姓名 **/
+ @Column
+ private String realName;
+ /** 电话 **/
+ @Column
+ private String phone;
+ /** 邮箱 **/
+ @Column
+ private String email;
+ /** 性别(0.未知|1.男|2.女) **/
+ @Column
+ private Gender gender;
+ /** 头像 **/
+ @Column
+ private String photo;
+ /** 生日 **/
+ @Column
+ private Date birthday;
+ /** 城市 **/
+ @Column
+ private Date city;
+ /** 身份证 **/
+ @Column
+ private String identity;
+ /** 密码 **/
+ @Column
+ private String password;
+ /** 是否为超级用户 **/
+ @Column
+ private Boolean superman;
+ /** 选项 **/
+ @Column
+ private UserCoreOptions options;
+ /** 状态(0.正常|1.锁定|2.待激活|3.注销) **/
+ @Column
+ private UserState userState;
+ /** 注册来源 **/
+ @Column
+ private UserSource userSource;
+
+ /** 获取租户编号 **/
+ public String getTenantCode() {
+ return tenantCode;
+ }
+
+ /** 设置租户编号 **/
+ public void setTenantCode(String tenantCode) {
+ this.tenantCode = tenantCode;
+ }
+
+ /** 获取用户类型 **/
+ public AccountType getUserType() {
+ return userType;
+ }
+
+ /** 设置用户类型 **/
+ public void setUserType(AccountType userType) {
+ this.userType = userType;
+ }
+
+ /** 获取部门ID **/
+ public String getDeptId() {
+ return deptId;
+ }
+
+ /** 设置部门ID **/
+ public void setDeptId(String deptId) {
+ this.deptId = deptId;
+ }
+
+ /** 获取账号/工号 **/
+ public String getUserCode() {
+ return userCode;
+ }
+
+ /** 设置账号/工号 **/
+ public void setUserCode(String userCode) {
+ this.userCode = userCode;
+ }
+
+ /** 获取登录用户名 **/
+ public String getUserName() {
+ return userName;
+ }
+
+ /** 设置登录用户名 **/
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ /** 获取昵称 **/
+ public String getNickName() {
+ return nickName;
+ }
+
+ /** 设置昵称 **/
+ public void setNickName(String nickName) {
+ this.nickName = nickName;
+ }
+
+ /** 获取真实姓名 **/
+ public String getRealName() {
+ return realName;
+ }
+
+ /** 设置真实姓名 **/
+ public void setRealName(String realName) {
+ this.realName = realName;
+ }
+
+ /** 获取电话 **/
+ public String getPhone() {
+ return phone;
+ }
+
+ /** 设置电话 **/
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ /** 获取邮箱 **/
+ public String getEmail() {
+ return email;
+ }
+
+ /** 设置邮箱 **/
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ /** 获取性别(0.未知|1.男|2.女) **/
+ public Gender getGender() {
+ return gender;
+ }
+
+ /** 设置性别(0.未知|1.男|2.女) **/
+ public void setGender(Gender gender) {
+ this.gender = gender;
+ }
+
+ /** 获取头像 **/
+ public String getPhoto() {
+ return photo;
+ }
+
+ /** 设置头像 **/
+ public void setPhoto(String photo) {
+ this.photo = photo;
+ }
+
+ /** 获取生日 **/
+ public Date getBirthday() {
+ return birthday;
+ }
+
+ /** 设置生日 **/
+ public void setBirthday(Date birthday) {
+ this.birthday = birthday;
+ }
+
+ /** 获取城市 **/
+ public Date getCity() {
+ return city;
+ }
+
+ /** 设置城市 **/
+ public void setCity(Date city) {
+ this.city = city;
+ }
+
+ /** 获取身份证 **/
+ public String getIdentity() {
+ return identity;
+ }
+
+ /** 设置身份证 **/
+ public void setIdentity(String identity) {
+ this.identity = identity;
+ }
+
+ /** 获取密码 **/
+ public String getPassword() {
+ return password;
+ }
+
+ /** 设置密码 **/
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ /** 获取是否为超级用户 **/
+ public Boolean getSuperman() {
+ return superman;
+ }
+
+ /** 设置是否为超级用户 **/
+ public void setSuperman(Boolean superman) {
+ this.superman = superman;
+ }
+
+ /** 获取状态(0.正常|1.锁定|2.待激活|3.注销) **/
+ public UserState getUserState() {
+ return userState;
+ }
+
+ /** 设置状态(0.正常|1.锁定|2.待激活|3.注销) **/
+ public void setUserState(UserState userState) {
+ this.userState = userState;
+ }
+
+ /** 获取选项 **/
+ public UserCoreOptions getOptions() {
+ return options;
+ }
+
+ /** 获取选项, force=是否强制返回非空选项 **/
+ public UserCoreOptions getOptions(boolean force) {
+ if (options == null && force) {
+ options = new UserCoreOptions();
+ }
+ return options;
+ }
+
+ /** 设置选项 **/
+ public void setOptions(UserCoreOptions options) {
+ this.options = options;
+ }
+
+ /** 获取注册来源 **/
+ public UserSource getUserSource() {
+ return userSource;
+ }
+
+ /** 设置注册来源 **/
+ public void setUserSource(UserSource userSource) {
+ this.userSource = userSource;
+ }
+
+ /** 获取用户的显示名称 **/
+ public String toDisplayName() {
+ if (nickName != null && nickName.length() > 0) {
+ return nickName;
+ } else if (realName != null && realName.length() > 0) {
+ return realName;
+ } else if (phone != null && phone.length() > 0) {
+ return phone;
+ } else if (email != null && email.length() > 0) {
+ return email;
+ } else if (userCode != null && userCode.length() > 0) {
+ return userCode;
+ } else if (userName != null && userName.length() > 0) {
+ return userName;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ String name = toDisplayName();
+ return name == null ? getId() : name;
+ }
+ }
+}
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveFindChildrenTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveFindChildrenTest.java
index d2f5539997dd11548f7b566c415fea0ba13bad53..6dc90c95dddf9cbb4346a88f3cfe505aeec712c7 100644
--- a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveFindChildrenTest.java
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveFindChildrenTest.java
@@ -1,6 +1,7 @@
package com.gitee.qdbp.jdbc.test.biz;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import com.gitee.qdbp.able.jdbc.condition.DbWhere;
import com.gitee.qdbp.able.jdbc.ordering.Orderings;
@@ -76,4 +77,48 @@ public class RecursiveFindChildrenTest extends AbstractTestNGSpringContextTests
// D010203是第3级, 每个3级有4个下级, 每个4级有5个下级
Assert.assertEquals(result.size(), 24, "testListDeptChildren");
}
+
+ @Test
+ public void testListDeptParentsBean() {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ String startCode = "D0101030403";
+ DbWhere filter = new DbWhere().on("tenantCode").equals("depttest").end();
+ DbWhere search = new DbWhere().on("deptCode").notEquals(startCode).end();
+ Orderings orderings = Orderings.of("parentCode, sortIndex");
+ List result = dao.listParents(startCode, "deptCode", "parentCode", filter, search, orderings);
+ Assert.assertEquals(result.size(), 4, "testListDeptParent");
+ }
+
+ @Test
+ public void testListDeptParentsBean2() {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ List startCode = Arrays.asList("D0101020303", "D0101030403");
+ DbWhere filter = new DbWhere().on("tenantCode").equals("depttest").end();
+ DbWhere search = new DbWhere().on("deptCode").notIn(startCode).end();
+ Orderings orderings = Orderings.of("parentCode, sortIndex");
+ List result = dao.listParents(startCode, "deptCode", "parentCode", filter, search, orderings);
+ Assert.assertEquals(result.size(), 6, "testListDeptParent");
+ }
+
+ @Test
+ public void testListDeptParentCodes() {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ String startCode = "D0101030403";
+ DbWhere filter = new DbWhere().on("tenantCode").equals("depttest").end();
+ DbWhere search = new DbWhere().on("deptCode").notEquals(startCode).end();
+ Orderings orderings = Orderings.of("parentCode, sortIndex");
+ List result = dao.listParentCodes(startCode, "deptCode", "parentCode", filter, search, orderings);
+ Assert.assertEquals(result.size(), 4, "testListDeptParent");
+ }
+
+ @Test
+ public void testListDeptParentCodes2() {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ List startCode = Arrays.asList("D0101020303", "D0101030403");
+ DbWhere filter = new DbWhere().on("tenantCode").equals("depttest").end();
+ DbWhere search = new DbWhere().on("deptCode").notIn(startCode).end();
+ Orderings orderings = Orderings.of("parentCode, sortIndex");
+ List result = dao.listParentCodes(startCode, "deptCode", "parentCode", filter, search, orderings);
+ Assert.assertEquals(result.size(), 6, "testListDeptParent");
+ }
}
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveQueryTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveQueryTest.java
index 7d18401756eb7b4d40e245a404a78c4c0dc682de..94fffe87a7091f3b14a0fab7bdb0e3452218543c 100644
--- a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveQueryTest.java
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/RecursiveQueryTest.java
@@ -5,6 +5,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
@@ -20,14 +22,17 @@ import com.gitee.qdbp.tools.excel.json.ExcelToJson;
import com.gitee.qdbp.tools.excel.json.ToJsonMetadata;
import com.gitee.qdbp.tools.excel.json.ToJsonProperties;
import com.gitee.qdbp.tools.files.PathTools;
+import com.gitee.qdbp.tools.utils.AssertTools;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.PropertyTools;
+import com.gitee.qdbp.tools.utils.StringTools;
@Test
@ContextConfiguration(locations = { "classpath:settings/spring/spring.xml" })
public class RecursiveQueryTest extends AbstractTestNGSpringContextTests {
- private static final String TACD = "DeptRecursive";
+ private static final String TACD = "DeptRecursive";
+ private static final Logger log = LoggerFactory.getLogger(RecursiveQueryTest.class);
@Autowired
private QdbcBoot qdbcBoot;
private final Map> childrenMaps = new HashMap<>();
@@ -98,6 +103,22 @@ public class RecursiveQueryTest extends AbstractTestNGSpringContextTests {
}
private void testListChildren(String deptCode) {
+ testListChildrenCodes(deptCode);
+ testListChildrenEntities(deptCode);
+ }
+
+ private void testListChildrenCodes(String deptCode) {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ DbWhere filter = new DbWhere().on("tenantCode").equals(TACD).end();
+ DbWhere search = DbWhere.NONE;
+ Orderings order = Orderings.of("parentCode, sortIndex");
+ List children = dao.listChildrenCodes(deptCode, "deptCode", "parentCode", filter, search, order);
+ int actual = children.size();
+ int expected = 1 + countChildren(childrenMaps, deptCode);
+ Assert.assertEquals(actual, expected, "Children size for '" + deptCode + "'");
+ }
+
+ private void testListChildrenEntities(String deptCode) {
CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
DbWhere filter = new DbWhere().on("tenantCode").equals(TACD).end();
DbWhere search = DbWhere.NONE;
@@ -110,54 +131,75 @@ public class RecursiveQueryTest extends AbstractTestNGSpringContextTests {
@Test(priority = 21)
public void testListParents100000() {
- testListParents("100000", 1);
+ testListParents("100000", "100000");
}
@Test(priority = 22)
public void testListParents320000() {
- testListParents("320000", 2);
+ testListParents("320000", "100000,320000");
}
@Test(priority = 23)
public void testListParents330000() {
- testListParents("330000", 2);
+ testListParents("330000", "100000,330000");
}
@Test(priority = 24)
public void testListParents320100() {
- testListParents("320100", 3);
+ testListParents("320100", "100000,320000,320100");
}
@Test(priority = 25)
public void testListParents340100() {
- testListParents("340100", 3);
+ testListParents("340100", "100000,340000,340100");
}
@Test(priority = 26)
public void testListParents320102() {
- testListParents("320102", 4);
+ testListParents("320102", "100000,320000,320100,320102");
}
@Test(priority = 27)
public void testListParents330110() {
- testListParents("330110", 4);
+ testListParents("330110", "100000,330000,330100,330110");
+ }
+
+ private void testListParents(String deptCode, String expected) {
+ testListParentCodes(deptCode, expected);
+ testListParentEntities(deptCode, expected);
}
- private void testListParents(String deptCode, int expected) {
+ private void testListParentCodes(String deptCode, String expected) {
CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
DbWhere filter = new DbWhere().on("tenantCode").equals(TACD).end();
DbWhere search = DbWhere.NONE;
- Orderings order = Orderings.of("parentCode, sortIndex");
- List children = dao.listParents(deptCode, "deptCode", "parentCode", filter, search, order);
- for (SysDeptEntity item : children) {
+ Orderings order = Orderings.NONE;
+ List codes = dao.listParentCodes(deptCode, "deptCode", "parentCode", filter, search, order);
+ log.debug("Parent codes of {}: {}", deptCode, ConvertTools.joinToString(codes));
+ List expectedCodes = StringTools.splits(expected, ',');
+ Assert.assertEquals(codes.size(), expectedCodes.size(), "Parents size for '" + deptCode + "'");
+ AssertTools.assertDeepEquals(codes, expectedCodes, "Parent codes");
+ }
+
+ private void testListParentEntities(String deptCode, String expected) {
+ CrudDao dao = qdbcBoot.crudDao(SysDeptEntity.class);
+ DbWhere filter = new DbWhere().on("tenantCode").equals(TACD).end();
+ DbWhere search = DbWhere.NONE;
+ Orderings order = Orderings.NONE;
+ List result = dao.listParents(deptCode, "deptCode", "parentCode", filter, search, order);
+ List codes = new ArrayList<>();
+ for (SysDeptEntity item : result) {
+ codes.add(item.getDeptCode());
Assert.assertNotNull(item.getId(), "listParents[result.id]");
Assert.assertNotNull(item.getDeptCode(), "listParents[result.deptCode]");
Assert.assertNotNull(item.getDeptName(), "listParents[result.deptName]");
Assert.assertNotNull(item.getParentCode(), "listParents[result.parentCode]");
Assert.assertNotNull(item.getDataState(), "listParents[result.dataState]");
}
- int actual = children.size();
- Assert.assertEquals(actual, expected, "Parents size for '" + deptCode + "'");
+ log.debug("Parent codes of {}: {}", deptCode, ConvertTools.joinToString(codes));
+ List expectedCodes = StringTools.splits(expected, ',');
+ Assert.assertEquals(result.size(), expectedCodes.size(), "Parents size for '" + deptCode + "'");
+ AssertTools.assertDeepEquals(codes, expectedCodes, "Parent codes");
}
// 统计子节点数量, 返回结果不包含自身节点
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/UserOrConditionTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/UserOrConditionTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..588676d13b421d9d1d6d497488d797640cd270f8
--- /dev/null
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/biz/UserOrConditionTest.java
@@ -0,0 +1,105 @@
+package com.gitee.qdbp.jdbc.test.biz;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import com.gitee.qdbp.able.beans.KeyString;
+import com.gitee.qdbp.able.jdbc.condition.DbWhere;
+import com.gitee.qdbp.jdbc.api.CrudDao;
+import com.gitee.qdbp.jdbc.api.QdbcBoot;
+import com.gitee.qdbp.jdbc.test.enums.Gender;
+import com.gitee.qdbp.jdbc.test.enums.UserSource;
+import com.gitee.qdbp.jdbc.test.enums.UserState;
+import com.gitee.qdbp.jdbc.test.enums.UserType;
+import com.gitee.qdbp.jdbc.test.model.SysUserEntity;
+
+/**
+ * 复杂的OR查询条件
+ *
+ * @author zhaohuihua
+ * @version 20210921
+ */
+@Test
+@ContextConfiguration(locations = {"classpath:settings/spring/spring.xml"})
+public class UserOrConditionTest extends AbstractTestNGSpringContextTests {
+
+ private static final String TACD = "UserOrCondition";
+ @Autowired
+ private QdbcBoot qdbcBoot;
+
+ @Test(priority = 1001)
+ public void testUserEntityDelete() {
+ DbWhere where = new DbWhere();
+ where.on("tenantCode").equals(TACD);
+ CrudDao dao = qdbcBoot.crudDao(SysUserEntity.class);
+ dao.physicalDelete(where);
+ }
+
+ @Test(priority = 1002)
+ public void testUserEntityCreate() {
+ CrudDao dao = qdbcBoot.crudDao(SysUserEntity.class);
+ SysUserEntity entity = new SysUserEntity();
+ entity.setTenantCode(TACD);
+ entity.setSuperman(false);
+ entity.setGender(Gender.FEMALE);
+ entity.setUserType(UserType.USER);
+ entity.setUserState(UserState.NORMAL);
+ entity.setUserSource(UserSource.INPUT);
+
+ entity.setId(null);
+ entity.setUserCode("kelly");
+ entity.setDeptId("A001");
+ entity.setCity("beijing");
+ dao.insert(entity);
+
+ entity.setId(null);
+ entity.setUserCode("evan");
+ entity.setDeptId("A001");
+ entity.setCity("nanjing");
+ dao.insert(entity);
+
+ entity.setId(null);
+ entity.setUserCode("coral");
+ entity.setDeptId("A002");
+ entity.setCity("nanjing");
+ dao.insert(entity);
+
+ entity.setId(null);
+ entity.setUserCode("jack");
+ entity.setDeptId("A002");
+ entity.setCity("beijing");
+ dao.insert(entity);
+ }
+
+ @Test(priority = 1003)
+ public void testOrConditionQuery() {
+ // deptId=A001且city=beijing 或 deptId=A002且city=nanjing
+ List conditions = new ArrayList<>();
+ conditions.add(new KeyString("A001", "beijing"));
+ conditions.add(new KeyString("A002", "nanjing"));
+
+ List userCodes = qdbcBoot.crudStream(SysUserEntity.class)
+ .where("tenantCode").equals(TACD)
+ .and()
+ .subCondition(where -> {
+ for (KeyString item : conditions) {
+ where.on().or().subCondition(w -> {
+ w.on("deptId").equals(item.getKey())
+ .and("city").equals(item.getValue());
+ });
+ }
+ })
+ .end()
+ .listFieldValues("userCode", false, String.class);
+
+ Assert.assertEquals(userCodes.size(), 2);
+ Assert.assertTrue(userCodes.contains("kelly"));
+ Assert.assertFalse(userCodes.contains("even"));
+ Assert.assertTrue(userCodes.contains("coral"));
+ Assert.assertFalse(userCodes.contains("jack"));
+ }
+}
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8d4ffb544bab1b2f53ed3614e31df32f7031d10
--- /dev/null
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.java
@@ -0,0 +1,46 @@
+package com.gitee.qdbp.jdbc.test.sql.build;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import com.gitee.qdbp.jdbc.api.QdbcBoot;
+import com.gitee.qdbp.jdbc.sql.SqlBuffer;
+import com.gitee.qdbp.tools.files.PathTools;
+import com.gitee.qdbp.tools.utils.AssertTools;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.annotations.Test;
+
+/**
+ * SqlOutTagTest
+ *
+ * @author zhaohuihua
+ * @version 20210911
+ */
+@Test
+@ContextConfiguration(locations = {"classpath:settings/spring/spring.xml"})
+public class SqlIncludeTagTest extends AbstractTestNGSpringContextTests {
+
+ @Autowired
+ private QdbcBoot qdbcBoot;
+
+ @Test
+ public void testSortIndex() throws IOException {
+ Map params = new HashMap<>();
+ params.put("tableName", "TEST_DEPARTMENT_CORE_INFO");
+ params.put("fieldName", "SORT_INDEX");
+ params.put("parentField", "PARETN_CODE");
+ params.put("parentValue", "A001");
+ params.put("dataState", 1);
+ String sqlId = "SqlIncludeTagTest:queryMaxIndex";
+ SqlBuffer sqlBuffer = qdbcBoot.sqlDao().getSqlContent(sqlId, params);
+ String sqlString = sqlBuffer.getLoggingSqlString();
+ System.out.println(sqlString);
+ String sqlFile = "SqlIncludeTagTest.sql";
+
+ URL resultUrl = PathTools.findClassResource(SqlBuilderPrintTest.class, sqlFile);
+ AssertTools.assertTextLinesEquals(sqlString, resultUrl);
+ }
+}
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.sql b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.sql
new file mode 100644
index 0000000000000000000000000000000000000000..6b008c8aacddb6bcf1e66f00ed0a744c2d9bd835
--- /dev/null
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/build/SqlIncludeTagTest.sql
@@ -0,0 +1,5 @@
+SELECT MAX(SORT_INDEX) FROM TEST_DEPARTMENT_CORE_INFO
+ WHERE PARETN_CODE='A001'/*$1*/
+ AND DATA_SATE=1/*$2*/
+ AND TEST_SATE=2/*$3*/
+ AND EFTFLAG='E'/*$4*/
\ No newline at end of file
diff --git a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/parse/SqlTemplateConflictTest.java b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/parse/SqlTemplateConflictTest.java
index dcdda2b2d3dd136a86f551f415bf26832dabcf18..3a9935838f625c8efc83f47e82f1deceb2fed0a3 100644
--- a/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/parse/SqlTemplateConflictTest.java
+++ b/jdbc-test/src/test/java/com/gitee/qdbp/jdbc/test/sql/parse/SqlTemplateConflictTest.java
@@ -102,6 +102,18 @@ public class SqlTemplateConflictTest extends AbstractTestNGSpringContextTests {
@Test
public void testSqlIdConflict8() {
+ // 出现在select.001.sql/select.002.sql/select.003.sql, 003的优先级更高
+ String sqlId = "user.roles.query8";
+ Map params = new HashMap<>();
+ params.put("userIds", "UB0000001");
+ SqlBuffer sql = qdbcBoot.sqlDao().getSqlContent(sqlId, params);
+ // 001/002中的SQL没有TENANT_CODE条件
+ String string = sql.getExecutableSqlString();
+ Assert.assertTrue(string.contains("TENANT_CODE"), "sql 'user.roles.query8' contains 'TENANT_CODE'");
+ }
+
+ @Test
+ public void testSqlIdConflict20() {
// 出现在select.dbversion.sql中
String sqlId = "select.dbversion";
SqlBuffer content = qdbcBoot.sqlContainer().generate(sqlId, null);
diff --git a/jdbc-test/src/test/resources/jdbc.mysql5.properties b/jdbc-test/src/test/resources/jdbc.mysql5.properties
new file mode 100644
index 0000000000000000000000000000000000000000..de1b12e7892aba7d401ab2b82026ab2bcf2416c0
--- /dev/null
+++ b/jdbc-test/src/test/resources/jdbc.mysql5.properties
@@ -0,0 +1,2 @@
+# jdbc
+jdbc.sys = mysql:develop:dev888pwd@127.0.0.1:3306/qdbpdev