diff --git a/src/org/redkale/source/DataDefaultSource.java b/src/org/redkale/source/DataDefaultSource.java index 9aa196e97..dcd2bcd51 100644 --- a/src/org/redkale/source/DataDefaultSource.java +++ b/src/org/redkale/source/DataDefaultSource.java @@ -71,6 +71,8 @@ public final class DataDefaultSource implements DataSource, Function fullloader = (t) -> querySheet(false, false, t, null, null, (FilterNode) null).list(true); public DataDefaultSource() throws IOException { @@ -119,6 +121,14 @@ public final class DataDefaultSource implements DataSource, Function 0"); + this.props.setProperty("notcontain-sql-template", "INSTR(${keystr}, ${column}) = 0"); + } else if (this.readPool.isSqlserver()) { + this.props.setProperty("contain-sql-template", "CHARINDEX(${column}, ${keystr}) > 0"); + this.props.setProperty("notcontain-sql-template", "CHARINDEX(${column}, ${keystr}) = 0"); + } + this.props.putAll(readprop); this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode")); } @@ -128,6 +138,14 @@ public final class DataDefaultSource implements DataSource, Function 0"); + this.props.setProperty("notcontain-sql-template", "INSTR(${keystr}, ${column}) = 0"); + } else if (this.readPool.isSqlserver()) { + this.props.setProperty("contain-sql-template", "CHARINDEX(${column}, ${keystr}) > 0"); + this.props.setProperty("notcontain-sql-template", "CHARINDEX(${column}, ${keystr}) = 0"); + } + this.props.putAll(readprop); this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode")); } @@ -288,7 +306,7 @@ public final class DataDefaultSource implements DataSource, Function EntityInfo loadEntityInfo(Class clazz) { - return EntityInfo.load(clazz, this.nodeid, this.cacheForbidden, fullloader); + return EntityInfo.load(clazz, this.nodeid, this.cacheForbidden, this.props, fullloader); } /** diff --git a/src/org/redkale/source/EntityInfo.java b/src/org/redkale/source/EntityInfo.java index 21cd6260f..fd000655d 100644 --- a/src/org/redkale/source/EntityInfo.java +++ b/src/org/redkale/source/EntityInfo.java @@ -57,6 +57,10 @@ public final class EntityInfo { private final Map> updateAttributeMap = new HashMap<>(); + final String containSQL; //用于反向LIKE使用 + + final String notcontainSQL; //用于反向LIKE使用 + final String querySQL; private final Attribute[] queryAttributes; //数据库中所有字段 @@ -91,7 +95,7 @@ public final class EntityInfo { final int allocationSize; //------------------------------------------------------------ - public static EntityInfo load(Class clazz, final int nodeid, final boolean cacheForbidden, + public static EntityInfo load(Class clazz, final int nodeid, final boolean cacheForbidden, final Properties conf, Function fullloader) { EntityInfo rs = entityInfos.get(clazz); if (rs != null) return rs; @@ -99,7 +103,7 @@ public final class EntityInfo { rs = entityInfos.get(clazz); if (rs == null) { if (nodeid < 0) throw new IllegalArgumentException("nodeid(" + nodeid + ") is illegal"); - rs = new EntityInfo(clazz, nodeid, cacheForbidden); + rs = new EntityInfo(clazz, nodeid, cacheForbidden, conf); entityInfos.put(clazz, rs); AutoLoad auto = clazz.getAnnotation(AutoLoad.class); if (rs.cache != null && auto != null && auto.value()) { @@ -115,7 +119,7 @@ public final class EntityInfo { return entityInfos.get(clazz); } - private EntityInfo(Class type, int nodeid, final boolean cacheForbidden) { + private EntityInfo(Class type, int nodeid, final boolean cacheForbidden, Properties conf) { this.type = type; //--------------------------------------------- this.nodeid = nodeid >= 0 ? nodeid : 0; @@ -239,6 +243,9 @@ public final class EntityInfo { } else { this.cache = null; } + if (conf == null) conf = new Properties(); + this.containSQL = conf.getProperty("contain-sql-template", "LOCATE(${keystr}, ${column}) > 0"); + this.notcontainSQL = conf.getProperty("notcontain-sql-template", "LOCATE(${keystr}, ${column}) = 0"); } public void createPrimaryValue(T src) { diff --git a/src/org/redkale/source/FilterExpress.java b/src/org/redkale/source/FilterExpress.java index 8dc74951d..28cf8714d 100644 --- a/src/org/redkale/source/FilterExpress.java +++ b/src/org/redkale/source/FilterExpress.java @@ -7,7 +7,9 @@ package org.redkale.source; /** * - *

详情见: http://www.redkale.org + *

+ * 详情见: http://www.redkale.org + * * @author zhangjx */ public enum FilterExpress { @@ -18,10 +20,17 @@ public enum FilterExpress { LESSTHAN("<"), GREATERTHANOREQUALTO(">="), LESSTHANOREQUALTO("<="), + LIKE("LIKE"), NOTLIKE("NOT LIKE"), - IGNORECASELIKE("LIKE"), //不区分大小写的 LIKE + IGNORECASELIKE("LIKE"), //不区分大小写的 LIKE IGNORECASENOTLIKE("NOT LIKE"), //不区分大小写的 NOT LIKE + + CONTAIN("CONTAIN"), //包含, 相当于反向LIKE + NOTCONTAIN("NOT CONTAIN"), //不包含, 相当于反向LIKE + IGNORECASECONTAIN("CONTAIN"), //不区分大小写的 CONTAIN + IGNORECASENOTCONTAIN("NOT CONTAIN"), //不区分大小写的 NOT CONTAIN + BETWEEN("BETWEEN"), NOTBETWEEN("NOT BETWEEN"), IN("IN"), diff --git a/src/org/redkale/source/FilterNode.java b/src/org/redkale/source/FilterNode.java index b2d5df42b..32f050d9b 100644 --- a/src/org/redkale/source/FilterNode.java +++ b/src/org/redkale/source/FilterNode.java @@ -217,9 +217,14 @@ public class FilterNode { if (express == ISNULL || express == ISNOTNULL) { return new StringBuilder().append(info.getSQLColumn(talis, column)).append(' ').append(express.value()); } - final CharSequence val = formatToString(express, getValue()); + CharSequence val = formatToString(express, getValue()); if (val == null) return null; StringBuilder sb = new StringBuilder(32); + if (express == CONTAIN) return info.containSQL.replace("${column}", info.getSQLColumn(talis, column)).replace("${keystr}", val); + if (express == IGNORECASECONTAIN) return info.containSQL.replace("${column}", "LOWER(" + info.getSQLColumn(talis, column) + ")").replace("${keystr}", val); + if (express == NOTCONTAIN) return info.notcontainSQL.replace("${column}", info.getSQLColumn(talis, column)).replace("${keystr}", val); + if (express == IGNORECASENOTCONTAIN) return info.notcontainSQL.replace("${column}", "LOWER(" + info.getSQLColumn(talis, column) + ")").replace("${keystr}", val); + if (express == IGNORECASELIKE || express == IGNORECASENOTLIKE) { sb.append("LOWER(").append(info.getSQLColumn(talis, column)).append(')'); } else { @@ -594,6 +599,64 @@ public class FilterNode { return "LOWER(" + field + ") " + express.value() + ' ' + formatToString(valstr2); } }; + case CONTAIN: + return new Predicate() { + + @Override + public boolean test(T t) { + Object rs = attr.get(t); + return rs != null && val.toString().contains(rs.toString()); + } + + @Override + public String toString() { + return "" + formatToString(val) + ' ' + express.value() + ' ' + field; + } + }; + case IGNORECASECONTAIN: + final String valstr3 = val.toString().toLowerCase(); + return new Predicate() { + + @Override + public boolean test(T t) { + Object rs = attr.get(t); + return rs != null && valstr3.contains(rs.toString().toLowerCase()); + } + + @Override + public String toString() { + return "" + formatToString(valstr3) + express.value() + ' ' + "LOWER(" + field + ") "; + } + }; + case NOTCONTAIN: + return new Predicate() { + + @Override + public boolean test(T t) { + Object rs = attr.get(t); + return rs == null || !val.toString().contains(rs.toString()); + } + + @Override + public String toString() { + return "" + formatToString(val) + ' ' + express.value() + ' ' + field; + } + }; + case IGNORECASENOTCONTAIN: + final String valstr4 = val.toString().toLowerCase(); + return new Predicate() { + + @Override + public boolean test(T t) { + Object rs = attr.get(t); + return rs == null || !valstr4.contains(rs.toString().toLowerCase()); + } + + @Override + public String toString() { + return "" + formatToString(valstr4) + express.value() + ' ' + "LOWER(" + field + ") "; + } + }; case BETWEEN: case NOTBETWEEN: Range range = (Range) val; @@ -844,7 +907,8 @@ public class FilterNode { if (express == ISNULL || express == ISNOTNULL) { sb.append(col).append(' ').append(express.value()); } else if (ev != null) { - sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev)); + boolean lower = (express == IGNORECASELIKE || express == IGNORECASENOTLIKE || express == IGNORECASECONTAIN || express == IGNORECASENOTCONTAIN); + sb.append(lower ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev)); } } return sb; @@ -863,6 +927,8 @@ public class FilterNode { value = "%" + value + '%'; } else if (express == IGNORECASELIKE || express == IGNORECASENOTLIKE) { value = "%" + value.toString().toLowerCase() + '%'; + } else if (express == IGNORECASECONTAIN || express == IGNORECASENOTCONTAIN) { + value = value.toString().toLowerCase(); } return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\''); } else if (value instanceof Range) { diff --git a/src/org/redkale/source/FilterNodeBean.java b/src/org/redkale/source/FilterNodeBean.java index 09f406f4c..639bbe845 100644 --- a/src/org/redkale/source/FilterNodeBean.java +++ b/src/org/redkale/source/FilterNodeBean.java @@ -347,7 +347,8 @@ public final class FilterNodeBean implements Comparable> { if (express == ISNULL || express == ISNOTNULL) { sb.append(col).append(' ').append(express.value()); } else { - sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(" ?"); + boolean lower = (express == IGNORECASELIKE || express == IGNORECASENOTLIKE || express == IGNORECASECONTAIN || express == IGNORECASENOTCONTAIN); + sb.append(lower ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(" ?"); } } return sb; diff --git a/src/org/redkale/source/JDBCPoolSource.java b/src/org/redkale/source/JDBCPoolSource.java index 2a830f35f..e97a09fa5 100644 --- a/src/org/redkale/source/JDBCPoolSource.java +++ b/src/org/redkale/source/JDBCPoolSource.java @@ -20,7 +20,9 @@ import javax.sql.*; /** * - *

详情见: http://www.redkale.org + *

+ * 详情见: http://www.redkale.org + * * @author zhangjx */ public class JDBCPoolSource { @@ -88,6 +90,14 @@ public class JDBCPoolSource { return source != null && source.getClass().getName().contains(".mysql."); } + public boolean isOracle() { + return source != null && source.getClass().getName().contains("oracle."); + } + + public boolean isSqlserver() { + return source != null && source.getClass().getName().contains(".sqlserver."); + } + private void watch() throws IOException { if (dataSource.conf == null || dataSource.name == null) return; final String file = dataSource.conf.getFile();