Compare commits
19 Commits
2.0.0.beta
...
2.0.0.beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70a75abf74 | ||
|
|
1aa97f8e79 | ||
|
|
b4000235ac | ||
|
|
4b93f29a1c | ||
|
|
4892a50670 | ||
|
|
2fe0ac0ef9 | ||
|
|
333ae72148 | ||
|
|
5fd5b7f303 | ||
|
|
528cf45f3f | ||
|
|
c7308e7320 | ||
|
|
e2a49eaab7 | ||
|
|
44bd6f235c | ||
|
|
601d15b513 | ||
|
|
9e93485a97 | ||
|
|
ad87b2115d | ||
|
|
27a587d31f | ||
|
|
fc8fa27602 | ||
|
|
f9aebc8ee3 | ||
|
|
1167da8f4c |
@@ -93,6 +93,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
this.register(String.class, StringSimpledCoder.instance);
|
this.register(String.class, StringSimpledCoder.instance);
|
||||||
this.register(StringConvertWrapper.class, StringConvertWrapperSimpledCoder.instance);
|
this.register(StringConvertWrapper.class, StringConvertWrapperSimpledCoder.instance);
|
||||||
this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
|
this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
|
||||||
|
this.register(StringBuilder.class, CharSequenceSimpledCoder.StringBuilderSimpledCoder.instance);
|
||||||
this.register(java.util.Date.class, DateSimpledCoder.instance);
|
this.register(java.util.Date.class, DateSimpledCoder.instance);
|
||||||
this.register(java.time.Duration.class, DurationSimpledCoder.instance);
|
this.register(java.time.Duration.class, DurationSimpledCoder.instance);
|
||||||
this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance);
|
this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance);
|
||||||
@@ -433,25 +434,32 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
|
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
|
||||||
if (type == null || column == null || entry == null) return false;
|
if (type == null || column == null || entry == null) return false;
|
||||||
|
Field field = null;
|
||||||
try {
|
try {
|
||||||
final Field field = type.getDeclaredField(column);
|
field = type.getDeclaredField(column);
|
||||||
String get = "get";
|
|
||||||
if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is";
|
|
||||||
char[] cols = column.toCharArray();
|
|
||||||
cols[0] = Character.toUpperCase(cols[0]);
|
|
||||||
String col2 = new String(cols);
|
|
||||||
try {
|
|
||||||
register(type.getMethod(get + col2), entry);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
register(type.getMethod("set" + col2, field.getType()), entry);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
return register(field, entry);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
String get = "get";
|
||||||
|
if (field != null && (field.getType() == boolean.class || field.getType() == Boolean.class)) get = "is";
|
||||||
|
char[] cols = column.toCharArray();
|
||||||
|
cols[0] = Character.toUpperCase(cols[0]);
|
||||||
|
final String bigColumn = new String(cols);
|
||||||
|
try {
|
||||||
|
register(type.getMethod(get + bigColumn), entry);
|
||||||
|
} catch (NoSuchMethodException mex) {
|
||||||
|
if (get.length() >= 3) { //get
|
||||||
|
try {
|
||||||
|
register(type.getMethod("is" + bigColumn), entry);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
register(type.getMethod("set" + bigColumn, field.getType()), entry);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
}
|
||||||
|
return field == null ? true : register(field, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
|
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ package org.redkale.convert.ext;
|
|||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CharSequence 的SimpledCoder实现
|
* CharSequence 的SimpledCoder实现
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: https://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
@@ -28,4 +30,20 @@ public class CharSequenceSimpledCoder<R extends Reader, W extends Writer> extend
|
|||||||
public CharSequence convertFrom(R in) {
|
public CharSequence convertFrom(R in) {
|
||||||
return in.readString();
|
return in.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class StringBuilderSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, StringBuilder> {
|
||||||
|
|
||||||
|
public static final StringBuilderSimpledCoder instance = new StringBuilderSimpledCoder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(W out, StringBuilder value) {
|
||||||
|
out.writeString(value == null ? null : value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringBuilder convertFrom(R in) {
|
||||||
|
String rs = in.readString();
|
||||||
|
return rs == null ? null : new StringBuilder(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
@@ -42,6 +43,8 @@ public class HttpRequest extends Request<HttpContext> {
|
|||||||
|
|
||||||
protected String requestURI;
|
protected String requestURI;
|
||||||
|
|
||||||
|
private byte[] queryBytes;
|
||||||
|
|
||||||
private long contentLength = -1;
|
private long contentLength = -1;
|
||||||
|
|
||||||
private String contentType;
|
private String contentType;
|
||||||
@@ -120,9 +123,15 @@ public class HttpRequest extends Request<HttpContext> {
|
|||||||
int qst = array.find(index, offset, (byte) '?');
|
int qst = array.find(index, offset, (byte) '?');
|
||||||
if (qst > 0) {
|
if (qst > 0) {
|
||||||
this.requestURI = array.toDecodeString(index, qst - index, charset).trim();
|
this.requestURI = array.toDecodeString(index, qst - index, charset).trim();
|
||||||
addParameter(array, qst + 1, offset - qst - 1);
|
this.queryBytes = array.getBytes(qst + 1, offset - qst - 1);
|
||||||
|
try {
|
||||||
|
addParameter(array, qst + 1, offset - qst - 1);
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.context.getLogger().log(Level.WARNING, "HttpRequest.addParameter error: " + array.toString(), e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.requestURI = array.toDecodeString(index, offset - index, charset).trim();
|
this.requestURI = array.toDecodeString(index, offset - index, charset).trim();
|
||||||
|
this.queryBytes = new byte[0];
|
||||||
}
|
}
|
||||||
index = ++offset;
|
index = ++offset;
|
||||||
this.protocol = array.toString(index, array.size() - index, charset).trim();
|
this.protocol = array.toString(index, array.size() - index, charset).trim();
|
||||||
@@ -488,6 +497,7 @@ public class HttpRequest extends Request<HttpContext> {
|
|||||||
this.method = null;
|
this.method = null;
|
||||||
this.protocol = null;
|
this.protocol = null;
|
||||||
this.requestURI = null;
|
this.requestURI = null;
|
||||||
|
this.queryBytes = null;
|
||||||
this.contentType = null;
|
this.contentType = null;
|
||||||
this.host = null;
|
this.host = null;
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
@@ -667,6 +677,15 @@ public class HttpRequest extends Request<HttpContext> {
|
|||||||
return requestURI;
|
return requestURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求参数的byte[]
|
||||||
|
*
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public byte[] getQueryBytes() {
|
||||||
|
return queryBytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 截取getRequestURI最后的一个/后面的部分
|
* 截取getRequestURI最后的一个/后面的部分
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ public @interface RetLabel {
|
|||||||
for (Field field : clazz.getFields()) {
|
for (Field field : clazz.getFields()) {
|
||||||
if (!Modifier.isStatic(field.getModifiers())) continue;
|
if (!Modifier.isStatic(field.getModifiers())) continue;
|
||||||
if (field.getType() != int.class) continue;
|
if (field.getType() != int.class) continue;
|
||||||
RetLabel info = field.getAnnotation(RetLabel.class);
|
RetLabel[] infos = field.getAnnotationsByType(RetLabel.class);
|
||||||
if (info == null) continue;
|
if (infos == null || infos.length == 0) continue;
|
||||||
int value;
|
int value;
|
||||||
try {
|
try {
|
||||||
value = field.getInt(null);
|
value = field.getInt(null);
|
||||||
@@ -58,7 +58,9 @@ public @interface RetLabel {
|
|||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rets.computeIfAbsent(info.locale(), (k) -> new HashMap<>()).put(value, info.value());
|
for (RetLabel info : infos) {
|
||||||
|
rets.computeIfAbsent(info.locale(), (k) -> new HashMap<>()).put(value, info.value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rets;
|
return rets;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.redkale.service;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用的结果对象,在常见的HTTP+JSON接口中返回的结果需要含结果码,错误信息,和实体对象。 <br>
|
* 通用的结果对象,在常见的HTTP+JSON接口中返回的结果需要含结果码,错误信息,和实体对象。 <br>
|
||||||
@@ -66,6 +67,14 @@ public class RetResult<T> {
|
|||||||
return CompletableFuture.completedFuture(new RetResult());
|
return CompletableFuture.completedFuture(new RetResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RetResult<Map<String, String>> map(String... items) {
|
||||||
|
return new RetResult(Utility.ofMap(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> RetResult<Map<K, V>> map(Object... items) {
|
||||||
|
return new RetResult(Utility.ofMap(items));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断结果是否成功返回, retcode = 0 视为成功, 否则视为错误码
|
* 判断结果是否成功返回, retcode = 0 视为成功, 否则视为错误码
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -15,17 +15,25 @@ package org.redkale.source;
|
|||||||
*/
|
*/
|
||||||
public enum ColumnExpress {
|
public enum ColumnExpress {
|
||||||
/**
|
/**
|
||||||
* 直接赋值 col = val
|
* 赋值 col = val
|
||||||
*/
|
*/
|
||||||
MOV,
|
MOV,
|
||||||
/**
|
/**
|
||||||
* 追加值 col = col + val
|
* 加值 col = col + val
|
||||||
*/
|
*/
|
||||||
INC,
|
INC,
|
||||||
/**
|
/**
|
||||||
* 乘值 col = col * val
|
* 乘值 col = col * val
|
||||||
*/
|
*/
|
||||||
MUL,
|
MUL,
|
||||||
|
/**
|
||||||
|
* 除值 col = col / val
|
||||||
|
*/
|
||||||
|
DIV,
|
||||||
|
/**
|
||||||
|
* 取模 col = col % val
|
||||||
|
*/
|
||||||
|
MOD,
|
||||||
/**
|
/**
|
||||||
* 与值 col = col & val
|
* 与值 col = col & val
|
||||||
*/
|
*/
|
||||||
|
|||||||
124
src/org/redkale/source/ColumnNodeValue.java
Normal file
124
src/org/redkale/source/ColumnNodeValue.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.source;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import static org.redkale.source.ColumnExpress.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作为ColumnValue的value字段值,用于复杂的字段表达式 。
|
||||||
|
* String 视为 字段名
|
||||||
|
* Number 视为 数值
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class ColumnNodeValue implements Serializable {
|
||||||
|
|
||||||
|
private Serializable left;//类型只能是String、Number、ColumnNode
|
||||||
|
|
||||||
|
private ColumnExpress express; //不能是MOV
|
||||||
|
|
||||||
|
private Serializable right;//类型只能是String、Number、ColumnNode
|
||||||
|
|
||||||
|
public ColumnNodeValue() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue(Serializable left, ColumnExpress express, Serializable right) {
|
||||||
|
if (express == null || express == ColumnExpress.MOV) throw new IllegalArgumentException("express cannot be null or MOV");
|
||||||
|
this.left = left;
|
||||||
|
this.express = express;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue create(Serializable left, ColumnExpress express, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, express, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue inc(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, INC, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue mul(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, MUL, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue div(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, DIV, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue mod(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, MOD, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue and(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, AND, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColumnNodeValue orr(Serializable left, Serializable right) {
|
||||||
|
return new ColumnNodeValue(left, ORR, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue inc(Serializable right) {
|
||||||
|
return any(INC, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue mul(Serializable right) {
|
||||||
|
return any(MUL, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue div(Serializable right) {
|
||||||
|
return any(DIV, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue mod(Serializable right) {
|
||||||
|
return any(MOD, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue and(Serializable right) {
|
||||||
|
return any(AND, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnNodeValue orr(Serializable right) {
|
||||||
|
return any(ORR, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ColumnNodeValue any(ColumnExpress express, Serializable right) {
|
||||||
|
ColumnNodeValue one = new ColumnNodeValue(this.left, this.express, this.right);
|
||||||
|
this.left = one;
|
||||||
|
this.express = express;
|
||||||
|
this.right = right;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeft(Serializable left) {
|
||||||
|
this.left = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnExpress getExpress() {
|
||||||
|
return express;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpress(ColumnExpress express) {
|
||||||
|
this.express = express;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRight(Serializable right) {
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{\"column\":" + ((left instanceof CharSequence) ? ("\"" + left + "\"") : left) + ", \"express\":" + express + ", \"value\":" + ((right instanceof CharSequence) ? ("\"" + right + "\"") : right) + "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,6 +86,31 @@ public class ColumnValue {
|
|||||||
return new ColumnValue(column, MUL, value);
|
return new ColumnValue(column, MUL, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回 {column} = {column} / {value} 操作
|
||||||
|
*
|
||||||
|
* @param column 字段名
|
||||||
|
* @param value 字段值
|
||||||
|
*
|
||||||
|
* @return ColumnValue
|
||||||
|
*/
|
||||||
|
public static ColumnValue div(String column, Serializable value) {
|
||||||
|
return new ColumnValue(column, DIV, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回 {column} = {column} % {value} 操作
|
||||||
|
*
|
||||||
|
* @param column 字段名
|
||||||
|
* @param value 字段值
|
||||||
|
*
|
||||||
|
* @return ColumnValue
|
||||||
|
*/
|
||||||
|
//不常用,防止开发者容易在mov时误输入mod
|
||||||
|
// public static ColumnValue mod(String column, Serializable value) {
|
||||||
|
// return new ColumnValue(column, MOD, value);
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回 {column} = {column} & {value} 操作
|
* 返回 {column} = {column} & {value} 操作
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -73,13 +73,15 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
|
|||||||
if (info.tableStrategy == null || !info.isTableNotExist(se)) throw se;
|
if (info.tableStrategy == null || !info.isTableNotExist(se)) throw se;
|
||||||
synchronized (info.tables) {
|
synchronized (info.tables) {
|
||||||
final String oldTable = info.table;
|
final String oldTable = info.table;
|
||||||
|
final String catalog = conn.getCatalog();
|
||||||
final String newTable = info.getTable(entitys[0]);
|
final String newTable = info.getTable(entitys[0]);
|
||||||
if (!info.tables.contains(newTable)) {
|
final String tablekey = newTable.indexOf('.') > 0 ? newTable : (catalog + '.' + newTable);
|
||||||
|
if (!info.tables.contains(tablekey)) {
|
||||||
try {
|
try {
|
||||||
Statement st = conn.createStatement();
|
Statement st = conn.createStatement();
|
||||||
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
|
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
|
||||||
st.close();
|
st.close();
|
||||||
info.tables.add(newTable);
|
info.tables.add(tablekey);
|
||||||
} catch (SQLException sqle) { //多进程并发时可能会出现重复建表
|
} catch (SQLException sqle) { //多进程并发时可能会出现重复建表
|
||||||
if (newTable.indexOf('.') > 0 && info.isTableNotExist(se)) {
|
if (newTable.indexOf('.') > 0 && info.isTableNotExist(se)) {
|
||||||
Statement st;
|
Statement st;
|
||||||
@@ -94,7 +96,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
|
|||||||
st = conn.createStatement();
|
st = conn.createStatement();
|
||||||
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
|
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
|
||||||
st.close();
|
st.close();
|
||||||
info.tables.add(newTable);
|
info.tables.add(tablekey);
|
||||||
} catch (SQLException sqle2) {
|
} catch (SQLException sqle2) {
|
||||||
logger.log(Level.SEVERE, "create table2(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle2);
|
logger.log(Level.SEVERE, "create table2(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle2);
|
||||||
}
|
}
|
||||||
@@ -141,7 +143,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
|
|||||||
if (obj != null && obj.getClass().isArray()) {
|
if (obj != null && obj.getClass().isArray()) {
|
||||||
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
|
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
|
||||||
} else {
|
} else {
|
||||||
sb.append(FilterNode.formatToString(obj));
|
sb.append(info.formatSQLValue(obj, sqlFormatter));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sb.append(ch);
|
sb.append(ch);
|
||||||
@@ -289,7 +291,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
|
|||||||
if (obj != null && obj.getClass().isArray()) {
|
if (obj != null && obj.getClass().isArray()) {
|
||||||
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
|
sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'");
|
||||||
} else {
|
} else {
|
||||||
sb.append(FilterNode.formatToString(obj));
|
sb.append(info.formatSQLValue(obj, sqlFormatter));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sb.append(ch);
|
sb.append(ch);
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
@Resource(name = "$")
|
@Resource(name = "$")
|
||||||
protected DataCacheListener cacheListener;
|
protected DataCacheListener cacheListener;
|
||||||
|
|
||||||
|
protected final BiFunction<EntityInfo, Object, CharSequence> sqlFormatter;
|
||||||
|
|
||||||
protected final BiConsumer futureCompleteConsumer = (r, t) -> {
|
protected final BiConsumer futureCompleteConsumer = (r, t) -> {
|
||||||
if (t != null) logger.log(Level.SEVERE, "CompletableFuture complete error", (Throwable) t);
|
if (t != null) logger.log(Level.SEVERE, "CompletableFuture complete error", (Throwable) t);
|
||||||
};
|
};
|
||||||
@@ -107,6 +109,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
Semaphore semaphore = maxconns > 0 ? new Semaphore(maxconns) : null;
|
Semaphore semaphore = maxconns > 0 ? new Semaphore(maxconns) : null;
|
||||||
this.readPool = createPoolSource(this, "read", queue, semaphore, readprop);
|
this.readPool = createPoolSource(this, "read", queue, semaphore, readprop);
|
||||||
this.writePool = createPoolSource(this, "write", queue, semaphore, writeprop);
|
this.writePool = createPoolSource(this, "write", queue, semaphore, writeprop);
|
||||||
|
this.sqlFormatter = (info, val) -> formatValueToString(info, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Local
|
@Local
|
||||||
@@ -284,7 +287,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> String formatValueToString(final EntityInfo<T> info, Object value) {
|
protected <T> CharSequence formatValueToString(final EntityInfo<T> info, Object value) {
|
||||||
final String dbtype = this.readPool.getDbtype();
|
final String dbtype = this.readPool.getDbtype();
|
||||||
if ("mysql".equals(dbtype)) {
|
if ("mysql".equals(dbtype)) {
|
||||||
if (value == null) return null;
|
if (value == null) return null;
|
||||||
@@ -296,7 +299,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
}
|
}
|
||||||
return String.valueOf(value);
|
return String.valueOf(value);
|
||||||
}
|
}
|
||||||
return info.formatToString(value);
|
return info.formatSQLValue(value, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------- insert -----------------------------
|
//----------------------------- insert -----------------------------
|
||||||
@@ -506,13 +509,13 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
|
|
||||||
protected <T> CompletableFuture<Integer> deleteCompose(final EntityInfo<T> info, final Serializable... pks) {
|
protected <T> CompletableFuture<Integer> deleteCompose(final EntityInfo<T> info, final Serializable... pks) {
|
||||||
if (pks.length == 1) {
|
if (pks.length == 1) {
|
||||||
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pks[0]));
|
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pks[0], sqlFormatter);
|
||||||
return deleteDB(info, null, sql);
|
return deleteDB(info, null, sql);
|
||||||
}
|
}
|
||||||
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " IN (";
|
String sql = "DELETE FROM " + info.getTable(pks[0]) + " WHERE " + info.getPrimarySQLColumn() + " IN (";
|
||||||
for (int i = 0; i < pks.length; i++) {
|
for (int i = 0; i < pks.length; i++) {
|
||||||
if (i > 0) sql += ',';
|
if (i > 0) sql += ',';
|
||||||
sql += FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pks[i]));
|
sql += info.formatSQLValue(info.getPrimarySQLColumn(), pks[i], sqlFormatter);
|
||||||
}
|
}
|
||||||
sql += ")";
|
sql += ")";
|
||||||
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
|
||||||
@@ -795,11 +798,11 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
|
|
||||||
protected <T> CompletableFuture<Integer> updateColumnCompose(final EntityInfo<T> info, Serializable pk, String column, final Serializable colval) {
|
protected <T> CompletableFuture<Integer> updateColumnCompose(final EntityInfo<T> info, Serializable pk, String column, final Serializable colval) {
|
||||||
if (colval instanceof byte[]) {
|
if (colval instanceof byte[]) {
|
||||||
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = " + prepareParamSign(1) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk));
|
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = " + prepareParamSign(1) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
|
||||||
return updateDB(info, null, sql, true, colval);
|
return updateDB(info, null, sql, true, colval);
|
||||||
} else {
|
} else {
|
||||||
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = "
|
String sql = "UPDATE " + info.getTable(pk) + " SET " + info.getSQLColumn(null, column) + " = "
|
||||||
+ formatValueToString(info, info.getSQLValue(column, colval)) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk));
|
+ info.formatSQLValue(column, colval, sqlFormatter) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
|
||||||
return updateDB(info, null, sql, false);
|
return updateDB(info, null, sql, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,7 +874,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
return updateDB(info, null, sql, true, colval);
|
return updateDB(info, null, sql, true, colval);
|
||||||
} else {
|
} else {
|
||||||
String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1))
|
String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1))
|
||||||
+ " SET " + info.getSQLColumn(alias, column) + " = " + formatValueToString(info, colval)
|
+ " SET " + info.getSQLColumn(alias, column) + " = " + info.formatSQLValue(colval, sqlFormatter)
|
||||||
+ ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2))
|
+ ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2))
|
||||||
: (" WHERE " + where + (join2 == null ? "" : (" AND " + join2))));
|
: (" WHERE " + where + (join2 == null ? "" : (" AND " + join2))));
|
||||||
return updateDB(info, null, sql, false);
|
return updateDB(info, null, sql, false);
|
||||||
@@ -934,17 +937,17 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
Attribute<T, Serializable> attr = info.getUpdateAttribute(col.getColumn());
|
Attribute<T, Serializable> attr = info.getUpdateAttribute(col.getColumn());
|
||||||
if (attr == null) throw new RuntimeException(info.getType() + " cannot found column " + col.getColumn());
|
if (attr == null) throw new RuntimeException(info.getType() + " cannot found column " + col.getColumn());
|
||||||
if (setsql.length() > 0) setsql.append(", ");
|
if (setsql.length() > 0) setsql.append(", ");
|
||||||
String c = info.getSQLColumn(null, col.getColumn());
|
String sqlColumn = info.getSQLColumn(null, col.getColumn());
|
||||||
if (col.getValue() instanceof byte[]) {
|
if (col.getValue() instanceof byte[]) {
|
||||||
if (blobs == null) blobs = new ArrayList<>();
|
if (blobs == null) blobs = new ArrayList<>();
|
||||||
blobs.add((byte[]) col.getValue());
|
blobs.add((byte[]) col.getValue());
|
||||||
setsql.append(c).append(" = ").append(prepareParamSign(++index));
|
setsql.append(sqlColumn).append(" = ").append(prepareParamSign(++index));
|
||||||
} else {
|
} else {
|
||||||
setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col));
|
setsql.append(sqlColumn).append(" = ").append(info.formatSQLValue(sqlColumn, attr, col, sqlFormatter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
|
if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
|
||||||
String sql = "UPDATE " + info.getTable(pk) + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk));
|
String sql = "UPDATE " + info.getTable(pk) + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
|
||||||
if (blobs == null) return updateDB(info, null, sql, false);
|
if (blobs == null) return updateDB(info, null, sql, false);
|
||||||
return updateDB(info, null, sql, true, blobs.toArray());
|
return updateDB(info, null, sql, true, blobs.toArray());
|
||||||
}
|
}
|
||||||
@@ -1016,13 +1019,13 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
Attribute<T, Serializable> attr = info.getUpdateAttribute(col.getColumn());
|
Attribute<T, Serializable> attr = info.getUpdateAttribute(col.getColumn());
|
||||||
if (attr == null) continue;
|
if (attr == null) continue;
|
||||||
if (setsql.length() > 0) setsql.append(", ");
|
if (setsql.length() > 0) setsql.append(", ");
|
||||||
String c = info.getSQLColumn(alias, col.getColumn());
|
String sqlColumn = info.getSQLColumn(alias, col.getColumn());
|
||||||
if (col.getValue() instanceof byte[]) {
|
if (col.getValue() instanceof byte[]) {
|
||||||
if (blobs == null) blobs = new ArrayList<>();
|
if (blobs == null) blobs = new ArrayList<>();
|
||||||
blobs.add((byte[]) col.getValue());
|
blobs.add((byte[]) col.getValue());
|
||||||
setsql.append(c).append(" = ").append(prepareParamSign(++index));
|
setsql.append(sqlColumn).append(" = ").append(prepareParamSign(++index));
|
||||||
} else {
|
} else {
|
||||||
setsql.append(c).append(" = ").append(info.formatSQLValue(c, attr, col));
|
setsql.append(sqlColumn).append(" = ").append(info.formatSQLValue(sqlColumn, attr, col, sqlFormatter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
|
if (setsql.length() < 1) return CompletableFuture.completedFuture(0);
|
||||||
@@ -1157,7 +1160,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
blobs.add((byte[]) val);
|
blobs.add((byte[]) val);
|
||||||
setsql.append(" = ").append(prepareParamSign(++index));
|
setsql.append(" = ").append(prepareParamSign(++index));
|
||||||
} else {
|
} else {
|
||||||
setsql.append(" = ").append(formatValueToString(info, val));
|
setsql.append(" = ").append(info.formatSQLValue(val, sqlFormatter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (neednode) {
|
if (neednode) {
|
||||||
@@ -1178,7 +1181,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
return updateDB(info, null, sql, true, blobs.toArray());
|
return updateDB(info, null, sql, true, blobs.toArray());
|
||||||
} else {
|
} else {
|
||||||
final Serializable id = (Serializable) info.getSQLValue(info.getPrimary(), entity);
|
final Serializable id = (Serializable) info.getSQLValue(info.getPrimary(), entity);
|
||||||
String sql = "UPDATE " + info.getTable(id) + " a SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(id);
|
String sql = "UPDATE " + info.getTable(id) + " a SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(id, sqlFormatter);
|
||||||
if (blobs == null) return updateDB(info, null, sql, false);
|
if (blobs == null) return updateDB(info, null, sql, false);
|
||||||
return updateDB(info, null, sql, true, blobs.toArray());
|
return updateDB(info, null, sql, true, blobs.toArray());
|
||||||
}
|
}
|
||||||
@@ -1501,13 +1504,14 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapCompose(final EntityInfo<T> info, final String keyColumn, final FilterFunc func, final String funcColumn, FilterNode node) {
|
protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapCompose(final EntityInfo<T> info, final String keyColumn, final FilterFunc func, final String funcColumn, FilterNode node) {
|
||||||
final String sqlkey = info.getSQLColumn(null, keyColumn);
|
final String keySqlColumn = info.getSQLColumn(null, keyColumn);
|
||||||
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
|
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
|
||||||
final Set<String> haset = new HashSet<>();
|
final Set<String> haset = new HashSet<>();
|
||||||
final CharSequence join = node == null ? null : node.createSQLJoin(this, false, joinTabalis, haset, info);
|
final CharSequence join = node == null ? null : node.createSQLJoin(this, false, joinTabalis, haset, info);
|
||||||
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
|
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
|
||||||
final String sql = "SELECT a." + sqlkey + ", " + func.getColumn((funcColumn == null || funcColumn.isEmpty() ? "*" : info.getSQLColumn("a", funcColumn)))
|
final String funcSqlColumn = func == null ? info.getSQLColumn("a", funcColumn) : func.getColumn((funcColumn == null || funcColumn.isEmpty() ? "*" : info.getSQLColumn("a", funcColumn)));
|
||||||
+ " FROM " + info.getTable(node) + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + " GROUP BY a." + sqlkey;
|
final String sql = "SELECT a." + keySqlColumn + ", " + funcSqlColumn
|
||||||
|
+ " FROM " + info.getTable(node) + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + " GROUP BY a." + keySqlColumn;
|
||||||
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " querycolumnmap sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " querycolumnmap sql=" + sql);
|
||||||
return queryColumnMapDB(info, sql, keyColumn);
|
return queryColumnMapDB(info, sql, keyColumn);
|
||||||
}
|
}
|
||||||
@@ -1557,7 +1561,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
|
|
||||||
protected <T> CompletableFuture<T> findCompose(final EntityInfo<T> info, final SelectColumn selects, Serializable pk) {
|
protected <T> CompletableFuture<T> findCompose(final EntityInfo<T> info, final SelectColumn selects, Serializable pk) {
|
||||||
String column = info.getPrimarySQLColumn();
|
String column = info.getPrimarySQLColumn();
|
||||||
final String sql = "SELECT " + info.getQueryColumns(null, selects) + " FROM " + info.getTable(pk) + " WHERE " + column + " = " + FilterNode.formatToString(info.getSQLValue(column, pk));
|
final String sql = "SELECT " + info.getQueryColumns(null, selects) + " FROM " + info.getTable(pk) + " WHERE " + column + " = " + info.formatSQLValue(column, pk, sqlFormatter);
|
||||||
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
|
||||||
return findDB(info, sql, true, selects);
|
return findDB(info, sql, true, selects);
|
||||||
}
|
}
|
||||||
@@ -1694,7 +1698,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <T> CompletableFuture<Serializable> findColumnCompose(final EntityInfo<T> info, String column, final Serializable defValue, final Serializable pk) {
|
protected <T> CompletableFuture<Serializable> findColumnCompose(final EntityInfo<T> info, String column, final Serializable defValue, final Serializable pk) {
|
||||||
final String sql = "SELECT " + info.getSQLColumn(null, column) + " FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk));
|
final String sql = "SELECT " + info.getSQLColumn(null, column) + " FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
|
||||||
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " find sql=" + sql);
|
||||||
return findColumnDB(info, sql, true, column, defValue);
|
return findColumnDB(info, sql, true, column, defValue);
|
||||||
}
|
}
|
||||||
@@ -1756,7 +1760,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <T> CompletableFuture<Boolean> existsCompose(final EntityInfo<T> info, Serializable pk) {
|
protected <T> CompletableFuture<Boolean> existsCompose(final EntityInfo<T> info, Serializable pk) {
|
||||||
final String sql = "SELECT COUNT(*) FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(info.getSQLValue(info.getPrimarySQLColumn(), pk));
|
final String sql = "SELECT COUNT(*) FROM " + info.getTable(pk) + " WHERE " + info.getPrimarySQLColumn() + " = " + info.formatSQLValue(info.getPrimarySQLColumn(), pk, sqlFormatter);
|
||||||
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists sql=" + sql);
|
||||||
return existsDB(info, sql, true);
|
return existsDB(info, sql, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,34 +265,37 @@ public final class EntityCache<T> {
|
|||||||
if (filter != null) stream = stream.filter(filter);
|
if (filter != null) stream = stream.filter(filter);
|
||||||
Collector<T, Map, ?> collector = null;
|
Collector<T, Map, ?> collector = null;
|
||||||
final Class valtype = funcAttr == null ? null : funcAttr.type();
|
final Class valtype = funcAttr == null ? null : funcAttr.type();
|
||||||
switch (func) {
|
if (func != null) {
|
||||||
case AVG:
|
switch (func) {
|
||||||
if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) {
|
case AVG:
|
||||||
collector = (Collector<T, Map, ?>) Collectors.averagingDouble((T t) -> ((Number) funcAttr.get(t)).doubleValue());
|
if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) {
|
||||||
} else {
|
collector = (Collector<T, Map, ?>) Collectors.averagingDouble((T t) -> ((Number) funcAttr.get(t)).doubleValue());
|
||||||
collector = (Collector<T, Map, ?>) Collectors.averagingLong((T t) -> ((Number) funcAttr.get(t)).longValue());
|
} else {
|
||||||
}
|
collector = (Collector<T, Map, ?>) Collectors.averagingLong((T t) -> ((Number) funcAttr.get(t)).longValue());
|
||||||
break;
|
}
|
||||||
case COUNT:
|
break;
|
||||||
collector = (Collector<T, Map, ?>) Collectors.counting();
|
case COUNT:
|
||||||
break;
|
collector = (Collector<T, Map, ?>) Collectors.counting();
|
||||||
case DISTINCTCOUNT:
|
break;
|
||||||
collector = (Collector<T, Map, ?>) Collectors.mapping((t) -> funcAttr.get(t), Collectors.toSet());
|
case DISTINCTCOUNT:
|
||||||
break;
|
collector = (Collector<T, Map, ?>) Collectors.mapping((t) -> funcAttr.get(t), Collectors.toSet());
|
||||||
case MAX:
|
break;
|
||||||
case MIN:
|
case MAX:
|
||||||
Comparator<T> comp = (o1, o2) -> o1 == null ? (o2 == null ? 0 : -1) : ((Comparable) funcAttr.get(o1)).compareTo(funcAttr.get(o2));
|
case MIN:
|
||||||
collector = (Collector<T, Map, ?>) ((func == MAX) ? Collectors.maxBy(comp) : Collectors.minBy(comp));
|
Comparator<T> comp = (o1, o2) -> o1 == null ? (o2 == null ? 0 : -1) : ((Comparable) funcAttr.get(o1)).compareTo(funcAttr.get(o2));
|
||||||
break;
|
collector = (Collector<T, Map, ?>) ((func == MAX) ? Collectors.maxBy(comp) : Collectors.minBy(comp));
|
||||||
case SUM:
|
break;
|
||||||
if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) {
|
case SUM:
|
||||||
collector = (Collector<T, Map, ?>) Collectors.summingDouble((T t) -> ((Number) funcAttr.get(t)).doubleValue());
|
if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) {
|
||||||
} else {
|
collector = (Collector<T, Map, ?>) Collectors.summingDouble((T t) -> ((Number) funcAttr.get(t)).doubleValue());
|
||||||
collector = (Collector<T, Map, ?>) Collectors.summingLong((T t) -> ((Number) funcAttr.get(t)).longValue());
|
} else {
|
||||||
}
|
collector = (Collector<T, Map, ?>) Collectors.summingLong((T t) -> ((Number) funcAttr.get(t)).longValue());
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Map rs = stream.collect(Collectors.groupingBy(t -> keyAttr.get(t), LinkedHashMap::new, collector));
|
Map rs = collector == null ? stream.collect(Collectors.toMap(t -> keyAttr.get(t), t -> funcAttr.get(t), (key1, key2) -> key2))
|
||||||
|
: stream.collect(Collectors.groupingBy(t -> keyAttr.get(t), LinkedHashMap::new, collector));
|
||||||
if (func == MAX || func == MIN) {
|
if (func == MAX || func == MIN) {
|
||||||
Map rs2 = new LinkedHashMap();
|
Map rs2 = new LinkedHashMap();
|
||||||
rs.forEach((x, y) -> {
|
rs.forEach((x, y) -> {
|
||||||
@@ -599,39 +602,17 @@ public final class EntityCache<T> {
|
|||||||
Serializable newval = null;
|
Serializable newval = null;
|
||||||
switch (express) {
|
switch (express) {
|
||||||
case INC:
|
case INC:
|
||||||
numb = (Number) attr.get(entity);
|
|
||||||
if (numb == null) {
|
|
||||||
numb = (Number) val;
|
|
||||||
} else {
|
|
||||||
numb = numb.longValue() + ((Number) val).longValue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MUL:
|
case MUL:
|
||||||
numb = (Number) attr.get(entity);
|
case DIV:
|
||||||
if (numb == null) {
|
case MOD:
|
||||||
numb = 0;
|
|
||||||
} else {
|
|
||||||
numb = numb.longValue() * ((Number) val).floatValue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AND:
|
case AND:
|
||||||
numb = (Number) attr.get(entity);
|
|
||||||
if (numb == null) {
|
|
||||||
numb = 0;
|
|
||||||
} else {
|
|
||||||
numb = numb.longValue() & ((Number) val).longValue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ORR:
|
case ORR:
|
||||||
numb = (Number) attr.get(entity);
|
numb = getValue((Number) attr.get(entity), express, val);
|
||||||
if (numb == null) {
|
|
||||||
numb = 0;
|
|
||||||
} else {
|
|
||||||
numb = numb.longValue() | ((Number) val).longValue();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MOV:
|
case MOV:
|
||||||
|
if (val instanceof ColumnNodeValue) val = updateColumnNodeValue(attr, entity, (ColumnNodeValue) val);
|
||||||
newval = val;
|
newval = val;
|
||||||
|
if (val instanceof Number) numb = (Number) val;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (numb != null) {
|
if (numb != null) {
|
||||||
@@ -663,6 +644,70 @@ public final class EntityCache<T> {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <V> Serializable updateColumnNodeValue(Attribute<T, V> attr, final T entity, ColumnNodeValue node) {
|
||||||
|
Serializable left = node.getLeft();
|
||||||
|
if (left instanceof CharSequence) {
|
||||||
|
left = info.getUpdateAttribute(left.toString()).get(entity);
|
||||||
|
} else if (left instanceof ColumnNodeValue) {
|
||||||
|
left = updateColumnNodeValue(attr, entity, (ColumnNodeValue) left);
|
||||||
|
}
|
||||||
|
Serializable right = node.getRight();
|
||||||
|
if (left instanceof CharSequence) {
|
||||||
|
right = info.getUpdateAttribute(right.toString()).get(entity);
|
||||||
|
} else if (left instanceof ColumnNodeValue) {
|
||||||
|
right = updateColumnNodeValue(attr, entity, (ColumnNodeValue) right);
|
||||||
|
}
|
||||||
|
return getValue((Number) left, node.getExpress(), right);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <V> Number getValue(Number numb, final ColumnExpress express, Serializable val) {
|
||||||
|
switch (express) {
|
||||||
|
case INC:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = (Number) val;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() + ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MUL:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = 0;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() * ((Number) val).floatValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = 0;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() / ((Number) val).floatValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOD:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = 0;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() % ((Number) val).intValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = 0;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() & ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ORR:
|
||||||
|
if (numb == null) {
|
||||||
|
numb = 0;
|
||||||
|
} else {
|
||||||
|
numb = numb.longValue() | ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return numb;
|
||||||
|
}
|
||||||
|
|
||||||
public Attribute<T, Serializable> getAttribute(String fieldname) {
|
public Attribute<T, Serializable> getAttribute(String fieldname) {
|
||||||
return info.getAttribute(fieldname);
|
return info.getAttribute(fieldname);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public final class EntityInfo<T> {
|
|||||||
//用于复制表结构使用
|
//用于复制表结构使用
|
||||||
final String tablecopySQL;
|
final String tablecopySQL;
|
||||||
|
|
||||||
//用于存在table_20160202类似这种分布式表
|
//用于存在database.table_20160202类似这种分布式表
|
||||||
final Set<String> tables = new HashSet<>();
|
final Set<String> tables = new HashSet<>();
|
||||||
|
|
||||||
//分表 策略
|
//分表 策略
|
||||||
@@ -894,9 +894,36 @@ public final class EntityInfo<T> {
|
|||||||
return handler.encrypt(fieldvalue);
|
return handler.encrypt(fieldvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值转换成带转义的数据库的值
|
||||||
|
*
|
||||||
|
* @param fieldname 字段名
|
||||||
|
* @param fieldvalue 字段值
|
||||||
|
* @param sqlFormatter 转义器
|
||||||
|
*
|
||||||
|
* @return CharSequence
|
||||||
|
*/
|
||||||
|
public CharSequence formatSQLValue(String fieldname, Serializable fieldvalue, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
|
||||||
|
Object val = getSQLValue(fieldname, fieldvalue);
|
||||||
|
return sqlFormatter == null ? formatToString(val) : sqlFormatter.apply(this, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值转换成带转义的数据库的值
|
||||||
|
*
|
||||||
|
* @param value 字段值
|
||||||
|
* @param sqlFormatter 转义器
|
||||||
|
*
|
||||||
|
* @return CharSequence
|
||||||
|
*/
|
||||||
|
public CharSequence formatSQLValue(Object value, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
|
||||||
|
return sqlFormatter == null ? formatToString(value) : sqlFormatter.apply(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字段值转换成数据库的值
|
* 字段值转换成数据库的值
|
||||||
*
|
*
|
||||||
|
* @param <F> 泛型
|
||||||
* @param attr Attribute
|
* @param attr Attribute
|
||||||
* @param entity 记录对象
|
* @param entity 记录对象
|
||||||
*
|
*
|
||||||
@@ -909,6 +936,21 @@ public final class EntityInfo<T> {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值转换成带转义的数据库的值
|
||||||
|
*
|
||||||
|
* @param <F> 泛型
|
||||||
|
* @param attr Attribute
|
||||||
|
* @param entity 记录对象
|
||||||
|
* @param sqlFormatter 转义器
|
||||||
|
*
|
||||||
|
* @return CharSequence
|
||||||
|
*/
|
||||||
|
public <F> CharSequence formatSQLValue(Attribute<T, F> attr, T entity, BiFunction<EntityInfo, Object, CharSequence> sqlFormatter) {
|
||||||
|
Object val = getSQLValue(attr, entity);
|
||||||
|
return sqlFormatter == null ? formatToString(val) : sqlFormatter.apply(this, val);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库的值转换成数字段值
|
* 数据库的值转换成数字段值
|
||||||
*
|
*
|
||||||
@@ -947,30 +989,68 @@ public final class EntityInfo<T> {
|
|||||||
/**
|
/**
|
||||||
* 拼接UPDATE给字段赋值的SQL片段
|
* 拼接UPDATE给字段赋值的SQL片段
|
||||||
*
|
*
|
||||||
* @param col 表字段名
|
* @param sqlColumn 表字段名
|
||||||
* @param attr Attribute
|
* @param attr Attribute
|
||||||
* @param cv ColumnValue
|
* @param cv ColumnValue
|
||||||
|
* @param formatter 转义器
|
||||||
*
|
*
|
||||||
* @return CharSequence
|
* @return CharSequence
|
||||||
*/
|
*/
|
||||||
protected CharSequence formatSQLValue(String col, Attribute<T, Serializable> attr, final ColumnValue cv) {
|
protected CharSequence formatSQLValue(String sqlColumn, Attribute<T, Serializable> attr, final ColumnValue cv, BiFunction<EntityInfo, Object, CharSequence> formatter) {
|
||||||
if (cv == null) return null;
|
if (cv == null) return null;
|
||||||
Object val = cv.getValue();
|
Object val = cv.getValue();
|
||||||
CryptHandler handler = attr.attach();
|
if (val instanceof ColumnNodeValue && cv.getExpress() == ColumnExpress.MOV) return formatSQLValue(attr, (ColumnNodeValue) val, formatter);
|
||||||
if (handler != null) val = handler.encrypt(val);
|
|
||||||
switch (cv.getExpress()) {
|
switch (cv.getExpress()) {
|
||||||
case INC:
|
case INC:
|
||||||
return new StringBuilder().append(col).append(" + ").append(val);
|
return new StringBuilder().append(sqlColumn).append(" + ").append(val);
|
||||||
case MUL:
|
case MUL:
|
||||||
return new StringBuilder().append(col).append(" * ").append(val);
|
return new StringBuilder().append(sqlColumn).append(" * ").append(val);
|
||||||
|
case DIV:
|
||||||
|
return new StringBuilder().append(sqlColumn).append(" / ").append(val);
|
||||||
|
case MOD:
|
||||||
|
return new StringBuilder().append(sqlColumn).append(" % ").append(val);
|
||||||
case AND:
|
case AND:
|
||||||
return new StringBuilder().append(col).append(" & ").append(val);
|
return new StringBuilder().append(sqlColumn).append(" & ").append(val);
|
||||||
case ORR:
|
case ORR:
|
||||||
return new StringBuilder().append(col).append(" | ").append(val);
|
return new StringBuilder().append(sqlColumn).append(" | ").append(val);
|
||||||
case MOV:
|
case MOV:
|
||||||
return formatToString(val);
|
CryptHandler handler = attr.attach();
|
||||||
|
if (handler != null) val = handler.encrypt(val);
|
||||||
|
return formatter == null ? formatToString(val) : formatter.apply(this, val);
|
||||||
}
|
}
|
||||||
return formatToString(val);
|
CryptHandler handler = attr.attach();
|
||||||
|
if (handler != null) val = handler.encrypt(val);
|
||||||
|
return formatter == null ? formatToString(val) : formatter.apply(this, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CharSequence formatSQLValue(Attribute<T, Serializable> attr, final ColumnNodeValue node, BiFunction<EntityInfo, Object, CharSequence> formatter) {
|
||||||
|
Serializable left = node.getLeft();
|
||||||
|
if (left instanceof CharSequence) {
|
||||||
|
left = this.getSQLColumn(null, left.toString());
|
||||||
|
} else if (left instanceof ColumnNodeValue) {
|
||||||
|
left = "(" + formatSQLValue(attr, (ColumnNodeValue) left, formatter) + ")";
|
||||||
|
}
|
||||||
|
Serializable right = node.getRight();
|
||||||
|
if (right instanceof CharSequence) {
|
||||||
|
right = this.getSQLColumn(null, right.toString());
|
||||||
|
} else if (left instanceof ColumnNodeValue) {
|
||||||
|
right = "(" + formatSQLValue(attr, (ColumnNodeValue) right, formatter) + ")";
|
||||||
|
}
|
||||||
|
switch (node.getExpress()) {
|
||||||
|
case INC:
|
||||||
|
return new StringBuilder().append(left).append(" + ").append(right);
|
||||||
|
case MUL:
|
||||||
|
return new StringBuilder().append(left).append(" * ").append(right);
|
||||||
|
case DIV:
|
||||||
|
return new StringBuilder().append(left).append(" / ").append(right);
|
||||||
|
case MOD:
|
||||||
|
return new StringBuilder().append(left).append(" % ").append(right);
|
||||||
|
case AND:
|
||||||
|
return new StringBuilder().append(left).append(" & ").append(right);
|
||||||
|
case ORR:
|
||||||
|
return new StringBuilder().append(left).append(" | ").append(right);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(node + " express cannot be null or MOV");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1021,7 +1101,7 @@ public final class EntityInfo<T> {
|
|||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
protected String formatToString(Object value) {
|
private String formatToString(Object value) {
|
||||||
if (value == null) return null;
|
if (value == null) return null;
|
||||||
if (value instanceof CharSequence) {
|
if (value instanceof CharSequence) {
|
||||||
return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\'').toString();
|
return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\'').toString();
|
||||||
|
|||||||
@@ -1811,7 +1811,7 @@ public class FilterNode { //FilterNode 不能实现Serializable接口, 否则
|
|||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static CharSequence formatToString(Object value) {
|
private static CharSequence formatToString(Object value) {
|
||||||
CharSequence sb = formatToString(null, value);
|
CharSequence sb = formatToString(null, value);
|
||||||
return sb == null ? null : sb.toString();
|
return sb == null ? null : sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,21 @@ public final class ByteArray {
|
|||||||
return Arrays.copyOf(content, count);
|
return Arrays.copyOf(content, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取byte[]
|
||||||
|
*
|
||||||
|
* @param offset 偏移位
|
||||||
|
* @param length 长度
|
||||||
|
*
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public byte[] getBytes(int offset, int length) {
|
||||||
|
if (length < 1) return new byte[0];
|
||||||
|
byte[] bs = new byte[length];
|
||||||
|
System.arraycopy(this.content, offset, bs, 0, length);
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取byte[]并清空
|
* 获取byte[]并清空
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ public final class Redkale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDotedVersion() {
|
public static String getDotedVersion() {
|
||||||
return "2.0.0";
|
return "2.0.0-beta3";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getMajorVersion() {
|
public static int getMajorVersion() {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getMinorVersion() {
|
public static int getMinorVersion() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user