From ed8719c27b1eb7b3eefb08e8f7335bbc9ad8cbfc Mon Sep 17 00:00:00 2001 From: redkale Date: Sat, 2 Dec 2023 11:12:02 +0800 Subject: [PATCH] =?UTF-8?q?FilterJoinType=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/redkale/source/EntityInfo.java | 9 ++-- .../org/redkale/source/FilterJoinColumn.java | 7 +++ .../org/redkale/source/FilterJoinNode.java | 46 +++++++++++----- .../org/redkale/source/FilterJoinType.java | 17 ++++++ .../java/org/redkale/source/FilterNodes.java | 2 +- .../redkale/test/source/FilterNodeTest.java | 53 +++++++++++-------- 6 files changed, 96 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/redkale/source/FilterJoinType.java diff --git a/src/main/java/org/redkale/source/EntityInfo.java b/src/main/java/org/redkale/source/EntityInfo.java index 5f1e59cf8..f611611ee 100644 --- a/src/main/java/org/redkale/source/EntityInfo.java +++ b/src/main/java/org/redkale/source/EntityInfo.java @@ -323,11 +323,14 @@ public final class EntityInfo { javax.persistence.Table t2 = type.getAnnotation(javax.persistence.Table.class); final String tableName0 = t1 != null ? t1.name() : (t2 != null ? t2.name() : null); final String tableCcatalog0 = t1 != null ? t1.catalog() : (t2 != null ? t2.catalog() : null); - + String table0 = Utility.isEmpty(tableName0) ? type.getSimpleName().toLowerCase() : tableName0; + if (Utility.isNotEmpty(tableCcatalog0)) { + table0 = tableCcatalog0 + '.' + table0; + } if (type.getAnnotation(org.redkale.persistence.VirtualEntity.class) != null || type.getAnnotation(org.redkale.source.VirtualEntity.class) != null || (source == null || "memory".equalsIgnoreCase(source.getType()))) { - this.table = null; + this.table = source == null && type.getAnnotation(org.redkale.persistence.VirtualEntity.class) == null ? table0 : null; this.tableOneArray = null; BiFunction> loader = null; try { @@ -350,7 +353,7 @@ public final class EntityInfo { if (tableName0 != null && !tableName0.isEmpty() && tableName0.indexOf('.') >= 0) { throw new SourceException(type + " have illegal table.name on @Table"); } - this.table = (tableCcatalog0 == null) ? type.getSimpleName().toLowerCase() : (tableCcatalog0.isEmpty()) ? (tableName0.isEmpty() ? type.getSimpleName().toLowerCase() : tableName0) : (tableCcatalog0 + '.' + (tableName0.isEmpty() ? type.getSimpleName().toLowerCase() : tableName0)); + this.table = table0; this.tableOneArray = new String[]{this.table}; } DistributeTable dt = type.getAnnotation(DistributeTable.class); diff --git a/src/main/java/org/redkale/source/FilterJoinColumn.java b/src/main/java/org/redkale/source/FilterJoinColumn.java index 528deb081..b5bc8d6d2 100644 --- a/src/main/java/org/redkale/source/FilterJoinColumn.java +++ b/src/main/java/org/redkale/source/FilterJoinColumn.java @@ -45,6 +45,13 @@ public @interface FilterJoinColumn { */ String[] columns(); + /** + * join类别 + * + * @return join类别 + */ + FilterJoinType type() default FilterJoinType.INNER; + /** * 备注描述 * diff --git a/src/main/java/org/redkale/source/FilterJoinNode.java b/src/main/java/org/redkale/source/FilterJoinNode.java index 31727354b..c63260979 100644 --- a/src/main/java/org/redkale/source/FilterJoinNode.java +++ b/src/main/java/org/redkale/source/FilterJoinNode.java @@ -22,6 +22,8 @@ import org.redkale.util.*; */ public class FilterJoinNode extends FilterNode { + private FilterJoinType joinType; + private Class joinClass; private EntityInfo joinEntity; //在调用createSQLJoin和isCacheUseable时会注入 @@ -31,7 +33,7 @@ public class FilterJoinNode extends FilterNode { public FilterJoinNode() { } - protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) { + protected FilterJoinNode(FilterJoinType joinType, Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) { Objects.requireNonNull(joinClass); Objects.requireNonNull(joinColumns); if (express == null && value != null) { @@ -44,6 +46,7 @@ public class FilterJoinNode extends FilterNode { } } this.joinClass = joinClass; + this.joinType = joinType; this.joinColumns = joinColumns; this.column = column; this.express = express == null ? EQ : FilterNodes.oldExpress(express); @@ -51,7 +54,7 @@ public class FilterJoinNode extends FilterNode { } protected FilterJoinNode(FilterJoinNode node) { - this(node.joinClass, node.joinColumns, node.column, node.express, node.value); + this(node.joinType, node.joinClass, node.joinColumns, node.column, node.express, node.value); this.joinEntity = node.joinEntity; this.or = node.or; this.nodes = node.nodes; @@ -120,11 +123,6 @@ public class FilterJoinNode extends FilterNode { return this; } - @Override - protected CharSequence createSQLExpress(AbstractDataSqlSource source, final EntityInfo info, final Map joinTabalis) { - return super.createSQLExpress(source, this.joinEntity == null ? info : this.joinEntity, joinTabalis); - } - @Override protected Predicate createPredicate(final EntityCache cache) { if (column == null && this.nodes == null) { @@ -261,9 +259,14 @@ public class FilterJoinNode extends FilterNode { return filter; } + @Override + protected CharSequence createSQLExpress(AbstractDataSqlSource source, final EntityInfo info, final Map joinTabalis) { + return super.createSQLExpress(source, this.joinEntity == null ? info : this.joinEntity, joinTabalis); + } + @Override protected CharSequence createSQLJoin(final Function func, final boolean update, final Map joinTabalis, final Set haset, final EntityInfo info) { - boolean morejoin = false; + boolean moreJoin = false; if (this.joinEntity == null) { if (this.joinClass != null) { this.joinEntity = func.apply(this.joinClass); @@ -275,7 +278,7 @@ public class FilterJoinNode extends FilterNode { if (joinNode.joinClass != null) { joinNode.joinEntity = func.apply(joinNode.joinClass); if (this.joinClass != null && this.joinClass != joinNode.joinClass) { - morejoin = true; + moreJoin = true; } } } @@ -289,7 +292,7 @@ public class FilterJoinNode extends FilterNode { sb.append(cs); } } - if (morejoin) { + if (moreJoin) { Set set = new HashSet<>(); if (this.joinClass != null) { set.add(this.joinClass); @@ -318,7 +321,7 @@ public class FilterJoinNode extends FilterNode { String[] joinColumns = node.joinColumns; int pos = joinColumns[0].indexOf('='); if (update) { - sb.append("[").append(node.joinEntity.getTable(node)).append(" ").append(joinTabalis.get(node.joinClass)).append(']'); + sb.append('[').append(node.joinEntity.getTable(node)).append(" ").append(joinTabalis.get(node.joinClass)).append(']'); sb.append('{').append(info.getSQLColumn("a", pos > 0 ? joinColumns[0].substring(0, pos) : joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), pos > 0 ? joinColumns[0].substring(pos + 1) : joinColumns[0])); for (int i = 1; i < joinColumns.length; i++) { pos = joinColumns[i].indexOf('='); @@ -326,7 +329,7 @@ public class FilterJoinNode extends FilterNode { } sb.append('}'); } else { - sb.append(" INNER JOIN ").append(node.joinEntity.getTable(node)).append(" ").append(joinTabalis.get(node.joinClass)) + sb.append(" ").append(node.joinType).append(" JOIN ").append(node.joinEntity.getTables(node)[0]).append(" ").append(joinTabalis.get(node.joinClass)) .append(" ON ").append(info.getSQLColumn("a", pos > 0 ? joinColumns[0].substring(0, pos) : joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), pos > 0 ? joinColumns[0].substring(pos + 1) : joinColumns[0])); for (int i = 1; i < joinColumns.length; i++) { pos = joinColumns[i].indexOf('='); @@ -361,7 +364,20 @@ public class FilterJoinNode extends FilterNode { @Override protected void putJoinTabalis(Map map) { if (this.joinClass != null && !map.containsKey(this.joinClass)) { - map.put(joinClass, "jt" + map.size()); //join_table_1 + char[] chs = this.joinClass.getSimpleName().toCharArray(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < chs.length; i++) { + char ch = chs[i]; + if (i == 0 || Character.isUpperCase(ch)) { + sb.append(Character.toLowerCase(ch)); + } + } + String alis = sb.toString(); + if (map.values().contains(alis)) { + map.put(joinClass, "jt" + map.size()); //join_table_1 + } else { + map.put(joinClass, alis); + } } if (this.nodes == null) { return; @@ -381,6 +397,10 @@ public class FilterJoinNode extends FilterNode { return toString(joinClass == null ? null : joinClass.getSimpleName()).toString(); } + public FilterJoinType getJoinType() { + return joinType; + } + public Class getJoinClass() { return joinClass; } diff --git a/src/main/java/org/redkale/source/FilterJoinType.java b/src/main/java/org/redkale/source/FilterJoinType.java new file mode 100644 index 000000000..55ac58f68 --- /dev/null +++ b/src/main/java/org/redkale/source/FilterJoinType.java @@ -0,0 +1,17 @@ +/* + * + */ +package org.redkale.source; + +/** + * JOIN表的类别 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @since 2.8.0 + */ +public enum FilterJoinType { + INNER; +} diff --git a/src/main/java/org/redkale/source/FilterNodes.java b/src/main/java/org/redkale/source/FilterNodes.java index 51ace080b..dcc7c8e80 100644 --- a/src/main/java/org/redkale/source/FilterNodes.java +++ b/src/main/java/org/redkale/source/FilterNodes.java @@ -517,7 +517,7 @@ public final class FilterNodes { } public static FilterJoinNode joinInner(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) { - return new FilterJoinNode(joinClass, joinColumns, column, express, value); + return new FilterJoinNode(FilterJoinType.INNER, joinClass, joinColumns, column, express, value); } //---------------------------------------------------------------------------------------------------- diff --git a/src/test/java/org/redkale/test/source/FilterNodeTest.java b/src/test/java/org/redkale/test/source/FilterNodeTest.java index 3818f931f..f15bd48af 100644 --- a/src/test/java/org/redkale/test/source/FilterNodeTest.java +++ b/src/test/java/org/redkale/test/source/FilterNodeTest.java @@ -27,6 +27,12 @@ public class FilterNodeTest { private static EntityInfo carEntity; + public static void main(String[] args) throws Throwable { + FilterNodeTest test = new FilterNodeTest(); + test.init(); + test.run(); + } + @BeforeAll public static void init() throws Exception { final Properties props = new Properties(); @@ -34,7 +40,7 @@ public class FilterNodeTest { func = (Class t) -> loadEntityInfo(t, false, props, null, fullloader); carEntity = loadEntityInfo(CarTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(CarTestTable.createList())); final EntityInfo userEntity = loadEntityInfo(UserTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(UserTestTable.createList())); - final EntityInfo typeEntity = loadEntityInfo(CarTypeTestTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(CarTypeTestTable.createList())); + final EntityInfo typeEntity = loadEntityInfo(CarTypeTable.class, false, props, null, (s, t) -> CompletableFuture.completedFuture(CarTypeTable.createList())); } private static EntityInfo loadEntityInfo(Class clazz, final boolean cacheForbidden, final Properties conf, DataSource source, BiFunction> fullloader) { @@ -102,24 +108,29 @@ public class FilterNodeTest { final CarTestBean bean = CarTestBean.create(); FilterNode joinNode1 = FilterNodes.joinInner(UserTestTable.class, new String[]{"userid", "username"}, "username", LIKE, bean.username) .or(FilterNodes.joinInner(UserTestTable.class, new String[]{"userid", "username"}, "createtime", GT, bean.createtime)); - FilterNode joinNode2 = FilterNodes.joinInner(CarTypeTestTable.class, "cartype", "typename", LIKE, bean.typename); + FilterNode joinNode2 = FilterNodes.joinInner(CarTypeTable.class, "cartype", "typename", LIKE, bean.typename); final FilterNode node = CarTestBean.caridTransient() ? (joinNode2.or(joinNode1)) : FilterNodes.gt("carid", bean.carid).and(joinNode1).or(joinNode2); final FilterNode beanNode = FilterNodeBean.createFilterNode(bean); System.out.println("node.string = " + node); System.out.println("bean.string = " + beanNode); - Assertions.assertEquals("(CarTypeTestTable.typename LIKE '%法拉利%' OR (UserTestTable.username LIKE '%用户1%' OR UserTestTable.createtime > 500))", node.toString()); + Assertions.assertEquals("(CarTypeTable.typename LIKE '%法拉利%' OR (UserTestTable.username LIKE '%用户1%' OR UserTestTable.createtime > 500))", node.toString()); Assertions.assertEquals(node.toString(), beanNode.toString()); Map nodeJoinTabalis = getJoinTabalis(node); Map beanJoinTabalis = getJoinTabalis(beanNode); + System.out.println("nodeJoinTabalis: " + nodeJoinTabalis); + System.out.println("beanJoinTabalis: " + beanJoinTabalis); CharSequence nodeJoinsql = createSQLJoin(node, func, false, nodeJoinTabalis, new HashSet<>(), carEntity); CharSequence beanJoinsql = createSQLJoin(beanNode, func, false, beanJoinTabalis, new HashSet<>(), carEntity); CharSequence nodeWhere = createSQLExpress(node, null, carEntity, nodeJoinTabalis); CharSequence beanWhere = createSQLExpress(beanNode, null, carEntity, beanJoinTabalis); + String expect = "SELECT a.* FROM cartesttable a INNER JOIN cartypetable ctt ON a.cartype = ctt.cartype INNER JOIN usertesttable utt ON a.userid = utt.userid AND a.username = utt.username WHERE (ctt.typename LIKE '%法拉利%' OR (utt.username LIKE '%用户1%' OR utt.createtime > 500))"; System.out.println("node.sql = SELECT a.* FROM " + CarTestTable.class.getSimpleName().toLowerCase() + " a" + (nodeJoinsql == null ? "" : nodeJoinsql) + " WHERE " + nodeWhere); System.out.println("bean.sql = SELECT a.* FROM " + CarTestTable.class.getSimpleName().toLowerCase() + " a" + (beanJoinsql == null ? "" : beanJoinsql) + " WHERE " + beanWhere); boolean r1 = isCacheUseable(node, func); Assertions.assertTrue(r1); - if (!r1) System.err.println("node.isCacheUseable 应该是true"); + if (!r1) { + System.err.println("node.isCacheUseable 应该是true"); + } boolean r2 = isCacheUseable(beanNode, func); Assertions.assertTrue(r2); @@ -148,7 +159,7 @@ public class FilterNodeTest { @FilterGroup("[OR]") @FilterColumn(express = LIKE) - @FilterJoinColumn(table = CarTypeTestTable.class, columns = {"cartype"}) + @FilterJoinColumn(table = CarTypeTable.class, columns = {"cartype"}) public String typename; @Override @@ -270,21 +281,21 @@ public class FilterNodeTest { @AutoLoad @Cacheable - public static class CarTypeTestTable { + public static class CarTypeTable { - public static List createList() { - List list = new ArrayList<>(); - list.add(new CarTypeTestTable(101, "奥迪A1")); - list.add(new CarTypeTestTable(102, "奥迪A2")); - list.add(new CarTypeTestTable(103, "奥迪A3")); - list.add(new CarTypeTestTable(104, "奥迪A4")); - list.add(new CarTypeTestTable(105, "奥迪A5")); - list.add(new CarTypeTestTable(201, "奔驰S1")); - list.add(new CarTypeTestTable(202, "奔驰S2")); - list.add(new CarTypeTestTable(203, "奔驰S3")); - list.add(new CarTypeTestTable(204, "奔驰S4")); - list.add(new CarTypeTestTable(205, "奔驰S5")); - list.add(new CarTypeTestTable(301, "法拉利")); + public static List createList() { + List list = new ArrayList<>(); + list.add(new CarTypeTable(101, "奥迪A1")); + list.add(new CarTypeTable(102, "奥迪A2")); + list.add(new CarTypeTable(103, "奥迪A3")); + list.add(new CarTypeTable(104, "奥迪A4")); + list.add(new CarTypeTable(105, "奥迪A5")); + list.add(new CarTypeTable(201, "奔驰S1")); + list.add(new CarTypeTable(202, "奔驰S2")); + list.add(new CarTypeTable(203, "奔驰S3")); + list.add(new CarTypeTable(204, "奔驰S4")); + list.add(new CarTypeTable(205, "奔驰S5")); + list.add(new CarTypeTable(301, "法拉利")); return list; } @@ -293,11 +304,11 @@ public class FilterNodeTest { private String typename; - public CarTypeTestTable() { + public CarTypeTable() { } - public CarTypeTestTable(int cartype, String typename) { + public CarTypeTable(int cartype, String typename) { this.cartype = cartype; this.typename = typename; }