diff --git a/src/main/java/org/redkale/net/AsyncIOThread.java b/src/main/java/org/redkale/net/AsyncIOThread.java index 369933dab..b8b7ad0c0 100644 --- a/src/main/java/org/redkale/net/AsyncIOThread.java +++ b/src/main/java/org/redkale/net/AsyncIOThread.java @@ -74,7 +74,7 @@ public class AsyncIOThread extends WorkThread { /** * 不可重置, 防止IO操作不在IO线程中执行 * - * @param command + * @param command 操作 */ @Override public void execute(Runnable command) { @@ -85,7 +85,7 @@ public class AsyncIOThread extends WorkThread { /** * 不可重置, 防止IO操作不在IO线程中执行 * - * @param commands + * @param commands 操作 */ @Override public void execute(Runnable... commands) { @@ -98,7 +98,7 @@ public class AsyncIOThread extends WorkThread { /** * 不可重置, 防止IO操作不在IO线程中执行 * - * @param commands + * @param commands 操作 */ @Override public void execute(Collection commands) { diff --git a/src/main/java/org/redkale/net/client/ClientCodec.java b/src/main/java/org/redkale/net/client/ClientCodec.java index dbbe2e8d8..ef69c45b4 100644 --- a/src/main/java/org/redkale/net/client/ClientCodec.java +++ b/src/main/java/org/redkale/net/client/ClientCodec.java @@ -27,18 +27,21 @@ import org.redkale.util.*; */ public abstract class ClientCodec implements CompletionHandler { - private final List> repsResults = new ArrayList<>(); + protected final ClientConnection connection; - private final ClientConnection connection; + private final List> respResults = new ArrayList<>(); private final ByteArray readArray = new ByteArray(); + private final ObjectPool respPool = ObjectPool.createUnsafePool(256, t -> new ClientResponse(), ClientResponse::prepare, ClientResponse::recycle); + public ClientCodec(ClientConnection connection) { + Objects.requireNonNull(connection); this.connection = connection; } //返回true: array会clear, 返回false: buffer会clear - public abstract boolean decodeMessages(ClientConnection connection, ByteBuffer buffer, ByteArray array); + public abstract boolean decodeMessages(ByteBuffer buffer, ByteArray array); @Override public final void completed(Integer count, ByteBuffer attachment) { @@ -61,27 +64,17 @@ public abstract class ClientCodec implements Complet AsyncConnection channel = connection.channel; Deque responseQueue = connection.responseQueue; Map responseMap = connection.responseMap; - if (decodeMessages(connection, buffer, readArray)) { //成功了 + if (decodeMessages(buffer, readArray)) { //成功了 readArray.clear(); - List> results = pollMessages(); - if (results != null) { - for (ClientResponse

rs : results) { - Serializable reqid = rs.getRequestid(); - ClientFuture respFuture = reqid == null ? responseQueue.poll() : responseMap.remove(reqid); - if (respFuture != null) { - int mergeCount = respFuture.getMergeCount(); - completeResponse(rs, respFuture); - if (mergeCount > 0) { - for (int i = 0; i < mergeCount; i++) { - respFuture = reqid == null ? responseQueue.poll() : responseMap.remove(reqid); - if (respFuture != null) { - completeResponse(rs, respFuture); - } - } - } - } + for (ClientResponse

cr : respResults) { + Serializable reqid = cr.getRequestid(); + ClientFuture respFuture = reqid == null ? responseQueue.poll() : responseMap.remove(reqid); + if (respFuture != null) { + completeResponse(respFuture, cr.message, cr.exc); } + respPool.accept(cr); } + respResults.clear(); if (buffer.hasRemaining()) { decodeResponse(buffer); @@ -97,40 +90,40 @@ public abstract class ClientCodec implements Complet } } - private void completeResponse(ClientResponse

rs, ClientFuture respFuture) { + private void completeResponse(ClientFuture respFuture, P message, Throwable exc) { if (respFuture != null) { ClientRequest request = respFuture.request; - if (!request.isCompleted()) { - if (rs.exc == null) { - connection.sendHalfWrite(rs.exc); - //request没有发送完,respFuture需要再次接收 - return; - } else { //异常了需要清掉半包 - connection.sendHalfWrite(rs.exc); - } - } - connection.respWaitingCounter.decrement(); - if (connection.isAuthenticated()) { - connection.client.incrRespDoneCounter(); - } try { + if (!request.isCompleted()) { + if (exc == null) { + connection.sendHalfWrite(exc); + //request没有发送完,respFuture需要再次接收 + return; + } else { //异常了需要清掉半包 + connection.sendHalfWrite(exc); + } + } + connection.respWaitingCounter.decrement(); + if (connection.isAuthenticated()) { + connection.client.incrRespDoneCounter(); + } respFuture.cancelTimeout(); //if (client.finest) client.logger.log(Level.FINEST, Utility.nowMillis() + ": " + Thread.currentThread().getName() + ": " + ClientConnection.this + ", 回调处理, req=" + request + ", message=" + rs.message); - connection.preComplete(rs.message, (R) request, rs.exc); + connection.preComplete(message, (R) request, exc); WorkThread workThread = request.workThread; request.workThread = null; if (workThread == null || workThread.getWorkExecutor() == null) { workThread = connection.channel.getReadIOThread(); } - if (rs.exc != null) { + if (exc != null) { workThread.runWork(() -> { Traces.currTraceid(request.traceid); - respFuture.completeExceptionally(rs.exc); + respFuture.completeExceptionally(exc); }); } else { workThread.runWork(() -> { Traces.currTraceid(request.traceid); - respFuture.complete(rs.message); + respFuture.complete(message); }); } } catch (Throwable t) { @@ -148,22 +141,18 @@ public abstract class ClientCodec implements Complet return connection.responseQueue.iterator(); } - public List> pollMessages() { - List> rs = new ArrayList<>(repsResults); - this.repsResults.clear(); + protected List> pollMessages() { + List> rs = new ArrayList<>(respResults); + this.respResults.clear(); return rs; } - public ClientConnection getConnection() { - return connection; + public void addMessage(R request, P result) { + this.respResults.add(respPool.get().set(request, result)); } - public void addMessage(P result) { - this.repsResults.add(new ClientResponse<>(result)); - } - - public void addMessage(Throwable exc) { - this.repsResults.add(new ClientResponse<>(exc)); + public void addMessage(R request, Throwable exc) { + this.respResults.add(respPool.get().set(request, exc)); } @Override diff --git a/src/main/java/org/redkale/net/client/ClientConnection.java b/src/main/java/org/redkale/net/client/ClientConnection.java index e1503eecc..a8855aaa6 100644 --- a/src/main/java/org/redkale/net/client/ClientConnection.java +++ b/src/main/java/org/redkale/net/client/ClientConnection.java @@ -37,7 +37,7 @@ public abstract class ClientConnection implements Co protected final AtomicBoolean pauseResuming = new AtomicBoolean(); - protected final List pauseRequests = new CopyOnWriteArrayList(); + protected final List pauseRequests = new CopyOnWriteArrayList<>(); protected final AsyncConnection channel; @@ -71,7 +71,6 @@ public abstract class ClientConnection implements Co ClientFuture respFuture = createClientFuture(request); int rts = this.channel.getReadTimeoutSeconds(); if (rts > 0 && !request.isCloseType()) { - respFuture.setConn(this); respFuture.setTimeout(client.timeoutScheduler.schedule(respFuture, rts, TimeUnit.SECONDS)); } respWaitingCounter.increment(); //放在writeChannelUnsafe计数会延迟,导致不准确 @@ -79,11 +78,11 @@ public abstract class ClientConnection implements Co return respFuture; } - CompletableFuture writeVirtualRequest(ClientRequest request) { + CompletableFuture writeVirtualRequest(R request) { if (!request.isVirtualType()) { return CompletableFuture.failedFuture(new RuntimeException("ClientVirtualRequest must be virtualType = true")); } - ClientFuture respFuture = new ClientFuture(request); + ClientFuture respFuture = createClientFuture(request); responseQueue.offer(respFuture); readChannel(); return respFuture; @@ -93,7 +92,7 @@ public abstract class ClientConnection implements Co } protected ClientFuture createClientFuture(R request) { - return new ClientFuture(request); + return new ClientFuture(this, request); } protected ClientConnection readChannel() { diff --git a/src/main/java/org/redkale/net/client/ClientFuture.java b/src/main/java/org/redkale/net/client/ClientFuture.java index 3e019d57c..170b72339 100644 --- a/src/main/java/org/redkale/net/client/ClientFuture.java +++ b/src/main/java/org/redkale/net/client/ClientFuture.java @@ -5,7 +5,7 @@ */ package org.redkale.net.client; -import java.util.Queue; +import java.util.*; import java.util.concurrent.*; import org.redkale.net.*; @@ -16,49 +16,16 @@ import org.redkale.net.*; */ public class ClientFuture extends CompletableFuture implements Runnable { - public static final ClientFuture EMPTY = new ClientFuture(null) { - @Override - public boolean complete(Object value) { - return true; - } - - @Override - public boolean completeExceptionally(Throwable ex) { - return true; - } - - @Override - void setConn(ClientConnection conn) { - } - - @Override - void setTimeout(ScheduledFuture timeout) { - } - - @Override - void incrMergeCount() { - } - - @Override - public void run() { - } - }; - protected final ClientRequest request; + protected final ClientConnection conn; + private ScheduledFuture timeout; - private int mergeCount; //合并的个数,不算自身 - - private ClientConnection conn; - - public ClientFuture(ClientRequest request) { + public ClientFuture(ClientConnection conn, ClientRequest request) { super(); - this.request = request; - } - - void setConn(ClientConnection conn) { this.conn = conn; + this.request = request; } void setTimeout(ScheduledFuture timeout) { @@ -71,20 +38,10 @@ public class ClientFuture extends CompletableFuture implements Runnable { } } - void incrMergeCount() { - mergeCount++; - } - - public int getMergeCount() { - return mergeCount; - } - @Override //JDK9+ public ClientFuture newIncompleteFuture() { - ClientFuture future = new ClientFuture<>(request); + ClientFuture future = new ClientFuture<>(conn, request); future.timeout = timeout; - future.mergeCount = mergeCount; - future.conn = conn; return future; } @@ -125,4 +82,9 @@ public class ClientFuture extends CompletableFuture implements Runnable { } workThread.runWork(() -> completeExceptionally(ex)); } + + @Override + public String toString() { + return getClass().getSimpleName() + "_" + Objects.hash(this) + "{conn = " + conn + ", request = " + request + "}"; + } } diff --git a/src/main/java/org/redkale/net/client/ClientRequest.java b/src/main/java/org/redkale/net/client/ClientRequest.java index 7f1931ce9..def9e68e5 100644 --- a/src/main/java/org/redkale/net/client/ClientRequest.java +++ b/src/main/java/org/redkale/net/client/ClientRequest.java @@ -27,6 +27,9 @@ public abstract class ClientRequest implements BiConsumer { + protected ClientRequest request; + protected P message; protected Throwable exc; - public Serializable getRequestid() { - return null; + public ClientResponse() { + } + + public ClientResponse(ClientRequest request, P message) { + this.request = request; + this.message = message; } - public ClientResponse(P result) { - this.message = result; - } - - public ClientResponse(Throwable exc) { + public ClientResponse(ClientRequest request, Throwable exc) { + this.request = request; this.exc = exc; } + public Serializable getRequestid() { + return request == null ? null : request.getRequestid(); + } + + public ClientResponse

set(ClientRequest request, P message) { + this.request = request; + this.message = message; + return this; + } + + public ClientResponse

set(ClientRequest request, Throwable exc) { + this.request = request; + this.exc = exc; + return this; + } + + protected void prepare() { + this.request = null; + this.message = null; + this.exc = null; + } + + protected boolean recycle() { + this.request = null; + this.message = null; + this.exc = null; + return true; + } + + public ClientRequest getRequest() { + return request; + } + + public void setRequest(ClientRequest request) { + this.request = request; + } + public P getMessage() { return message; } @@ -53,4 +93,5 @@ public class ClientResponse

{ } return "{\"message\":" + message + "}"; } + } diff --git a/src/main/java/org/redkale/net/client/ClientWriteIOThread.java b/src/main/java/org/redkale/net/client/ClientWriteIOThread.java index 6c0eb266d..34a1188e3 100644 --- a/src/main/java/org/redkale/net/client/ClientWriteIOThread.java +++ b/src/main/java/org/redkale/net/client/ClientWriteIOThread.java @@ -18,7 +18,7 @@ import org.redkale.util.*; */ public class ClientWriteIOThread extends AsyncIOThread { - private final BlockingDeque requestQueue = new LinkedBlockingDeque<>(); + private final BlockingDeque requestQueue = new LinkedBlockingDeque<>(); public ClientWriteIOThread(String name, int index, int threads, ExecutorService workExecutor, Selector selector, ObjectPool unsafeBufferPool, ObjectPool safeBufferPool) { @@ -26,7 +26,7 @@ public class ClientWriteIOThread extends AsyncIOThread { } public void offerRequest(ClientConnection conn, ClientRequest request, ClientFuture respFuture) { - requestQueue.offer(new ClientEntity(conn, request, respFuture)); + requestQueue.offer(respFuture); } public void sendHalfWrite(ClientConnection conn, Throwable halfRequestExc) { @@ -37,7 +37,7 @@ public class ClientWriteIOThread extends AsyncIOThread { conn.pauseRequests.removeIf(e -> { if (e != null) { if (!skipFirst.compareAndSet(true, false)) { - requestQueue.offer((ClientEntity) e); + requestQueue.offer((ClientFuture) e); } } return true; @@ -57,62 +57,62 @@ public class ClientWriteIOThread extends AsyncIOThread { final ByteBuffer buffer = getBufferSupplier().get(); final int capacity = buffer.capacity(); final ByteArray writeArray = new ByteArray(1024 * 32); - final Map> map = new HashMap<>(); + final Map> map = new HashMap<>(); final ObjectPool listPool = ObjectPool.createUnsafePool(Utility.cpus() * 2, () -> new ArrayList(), null, t -> { t.clear(); return true; }); while (!isClosed()) { - ClientEntity entity; + ClientFuture entry; try { - while ((entity = requestQueue.take()) != null) { + while ((entry = requestQueue.take()) != null) { map.clear(); { - Serializable reqid = entity.request.getRequestid(); + Serializable reqid = entry.request.getRequestid(); if (reqid == null) { - entity.conn.responseQueue.offer(entity.respFuture); + entry.conn.responseQueue.offer(entry); } else { - entity.conn.responseMap.put(reqid, entity.respFuture); + entry.conn.responseMap.put(reqid, entry); } } - if (entity.conn.pauseWriting.get()) { - if (entity.conn.pauseResuming.get()) { + if (entry.conn.pauseWriting.get()) { + if (entry.conn.pauseResuming.get()) { try { - synchronized (entity.conn.pauseRequests) { - entity.conn.pauseRequests.wait(3_000); + synchronized (entry.conn.pauseRequests) { + entry.conn.pauseRequests.wait(3_000); } } catch (InterruptedException ie) { } } - entity.conn.pauseRequests.add(entity); + entry.conn.pauseRequests.add(entry); } else { - map.computeIfAbsent(entity.conn, c -> listPool.get()).add(entity); + map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry); } - while ((entity = requestQueue.poll()) != null) { - Serializable reqid = entity.request.getRequestid(); + while ((entry = requestQueue.poll()) != null) { + Serializable reqid = entry.request.getRequestid(); if (reqid == null) { - entity.conn.responseQueue.offer(entity.respFuture); + entry.conn.responseQueue.offer(entry); } else { - entity.conn.responseMap.put(reqid, entity.respFuture); + entry.conn.responseMap.put(reqid, entry); } - if (entity.conn.pauseWriting.get()) { - if (entity.conn.pauseResuming.get()) { + if (entry.conn.pauseWriting.get()) { + if (entry.conn.pauseResuming.get()) { try { - synchronized (entity.conn.pauseRequests) { - entity.conn.pauseRequests.wait(3_000); + synchronized (entry.conn.pauseRequests) { + entry.conn.pauseRequests.wait(3_000); } } catch (InterruptedException ie) { } } - entity.conn.pauseRequests.add(entity); + entry.conn.pauseRequests.add(entry); } else { - map.computeIfAbsent(entity.conn, c -> listPool.get()).add(entity); + map.computeIfAbsent(entry.conn, c -> listPool.get()).add(entry); } } map.forEach((conn, list) -> { writeArray.clear(); int i = -1; - for (ClientEntity en : list) { + for (ClientFuture en : list) { ++i; ClientRequest request = en.request; request.accept(conn, writeArray); @@ -153,23 +153,4 @@ public class ClientWriteIOThread extends AsyncIOThread { } }; - protected static class ClientEntity { - - ClientConnection conn; - - ClientRequest request; - - ClientFuture respFuture; - - public ClientEntity(ClientConnection conn, ClientRequest request, ClientFuture respFuture) { - this.conn = conn; - this.request = request; - this.respFuture = respFuture; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "_" + Objects.hash(this) + "{conn = " + conn + ", request = " + request + "}"; - } - } } diff --git a/src/main/java/org/redkale/net/http/HttpResponse.java b/src/main/java/org/redkale/net/http/HttpResponse.java index d8381910e..1a9e49847 100644 --- a/src/main/java/org/redkale/net/http/HttpResponse.java +++ b/src/main/java/org/redkale/net/http/HttpResponse.java @@ -1405,7 +1405,7 @@ public class HttpResponse extends Response { /** * 判断是否存在Header值 * - * @param name + * @param name header-name * * @return 是否存在 */ diff --git a/src/main/java/org/redkale/net/sncp/SncpDispatcherServlet.java b/src/main/java/org/redkale/net/sncp/SncpDispatcherServlet.java index b22c306bb..4e22d6b50 100644 --- a/src/main/java/org/redkale/net/sncp/SncpDispatcherServlet.java +++ b/src/main/java/org/redkale/net/sncp/SncpDispatcherServlet.java @@ -26,7 +26,7 @@ public class SncpDispatcherServlet extends DispatcherServlet { this.addrBytes = context.getServerAddress().getAddress().getAddress(); this.addrPort = context.getServerAddress().getPort(); if (this.addrBytes.length != 4) { - throw new RuntimeException("SNCP serverAddress only support IPv4"); + throw new SncpException("SNCP serverAddress only support IPv4"); } } diff --git a/src/main/java/org/redkale/source/DataSqlSource.java b/src/main/java/org/redkale/source/DataSqlSource.java index 05f85e202..9ca48710d 100644 --- a/src/main/java/org/redkale/source/DataSqlSource.java +++ b/src/main/java/org/redkale/source/DataSqlSource.java @@ -1867,7 +1867,7 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi final EntityInfo info = loadEntityInfo(clazz); String illegalColumn = checkIllegalColumn(info, selects); if (illegalColumn != null) { - return CompletableFuture.failedFuture(new RuntimeException(info.getType() + " cannot found column " + illegalColumn)); + return CompletableFuture.failedFuture(new SourceException(info.getType() + " cannot found column " + illegalColumn)); } if (isOnlyCache(info)) { return CompletableFuture.completedFuture(updateCache(info, -1, false, entity, null, selects)); @@ -1929,7 +1929,7 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi final EntityInfo info = loadEntityInfo(clazz); String illegalColumn = checkIllegalColumn(info, selects); if (illegalColumn != null) { - return CompletableFuture.failedFuture(new RuntimeException(info.getType() + " cannot found column " + illegalColumn)); + return CompletableFuture.failedFuture(new SourceException(info.getType() + " cannot found column " + illegalColumn)); } if (isOnlyCache(info)) { return CompletableFuture.completedFuture(updateCache(info, -1, true, entity, node, selects)); @@ -2571,15 +2571,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return rs; } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = findSql(info, selects, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " find sql=" + sql); } if (isAsync()) { - return findDBAsync(info, new String[]{table}, sql, true, selects, pk, null).join(); + return findDBAsync(info, tables, sql, true, selects, pk, null).join(); } else { - return findDB(info, new String[]{table}, sql, true, selects, pk, null); + return findDB(info, tables, sql, true, selects, pk, null); } } @@ -2593,15 +2593,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return CompletableFuture.completedFuture(rs); } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = findSql(info, selects, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " find sql=" + sql); } if (isAsync()) { - return findDBAsync(info, new String[]{table}, sql, true, selects, pk, null); + return findDBAsync(info, tables, sql, true, selects, pk, null); } else { - return supplyAsync(() -> findDB(info, new String[]{table}, sql, true, selects, pk, null)); + return supplyAsync(() -> findDB(info, tables, sql, true, selects, pk, null)); } } @@ -2692,15 +2692,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return val; } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = findColumnSql(info, column, defValue, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " findColumn sql=" + sql); } if (isAsync()) { - return findColumnDBAsync(info, new String[]{table}, sql, true, column, defValue, pk, null).join(); + return findColumnDBAsync(info, tables, sql, true, column, defValue, pk, null).join(); } else { - return findColumnDB(info, new String[]{table}, sql, true, column, defValue, pk, null); + return findColumnDB(info, tables, sql, true, column, defValue, pk, null); } } @@ -2714,15 +2714,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return CompletableFuture.completedFuture(val); } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = findColumnSql(info, column, defValue, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " findColumn sql=" + sql); } if (isAsync()) { - return findColumnDBAsync(info, new String[]{table}, sql, true, column, defValue, pk, null); + return findColumnDBAsync(info, tables, sql, true, column, defValue, pk, null); } else { - return supplyAsync(() -> findColumnDB(info, new String[]{table}, sql, true, column, defValue, pk, null)); + return supplyAsync(() -> findColumnDB(info, tables, sql, true, column, defValue, pk, null)); } } @@ -2819,15 +2819,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return rs; } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = existsSql(info, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " exists sql=" + sql); } if (isAsync()) { - return existsDBAsync(info, new String[]{table}, sql, true, pk, null).join(); + return existsDBAsync(info, tables, sql, true, pk, null).join(); } else { - return existsDB(info, new String[]{table}, sql, true, pk, null); + return existsDB(info, tables, sql, true, pk, null); } } @@ -2841,15 +2841,15 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi return CompletableFuture.completedFuture(rs); } } - String table = info.getTable(pk); + String[] tables = info.getTableOneArray(pk); String sql = existsSql(info, pk); if (info.isLoggable(logger, Level.FINEST, sql)) { logger.finest(info.getType().getSimpleName() + " exists sql=" + sql); } if (isAsync()) { - return existsDBAsync(info, new String[]{table}, sql, true, pk, null); + return existsDBAsync(info, tables, sql, true, pk, null); } else { - return supplyAsync(() -> existsDB(info, new String[]{table}, sql, true, pk, null)); + return supplyAsync(() -> existsDB(info, tables, sql, true, pk, null)); } } diff --git a/src/main/java/org/redkale/source/EntityInfo.java b/src/main/java/org/redkale/source/EntityInfo.java index 9ccbefa62..5c69d9e1c 100644 --- a/src/main/java/org/redkale/source/EntityInfo.java +++ b/src/main/java/org/redkale/source/EntityInfo.java @@ -45,6 +45,9 @@ public final class EntityInfo { //类对应的数据表名, 如果是VirtualEntity 类, 则该字段为null final String table; + //table的单一元素数组 + final String[] tableOneArray; + //JsonConvert final JsonConvert jsonConvert; @@ -66,6 +69,9 @@ public final class EntityInfo { //主键 final Attribute primary; + //table的单一元素数组 + final Attribute[] primaryOneArray; + //DDL字段集合 final EntityColumn[] ddlColumns; @@ -294,6 +300,7 @@ public final class EntityInfo { || type.getAnnotation(org.redkale.source.VirtualEntity.class) != null || (source == null || "memory".equalsIgnoreCase(source.getType()))) { this.table = null; + this.tableOneArray = null; BiFunction> loader = null; try { org.redkale.persistence.VirtualEntity ve = type.getAnnotation(org.redkale.persistence.VirtualEntity.class); @@ -316,6 +323,7 @@ public final class EntityInfo { 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.tableOneArray = new String[]{this.table}; } DistributeTable dt = type.getAnnotation(DistributeTable.class); DistributeTableStrategy dts = null; @@ -456,6 +464,7 @@ public final class EntityInfo { this.jsonConvert = convert == null ? DEFAULT_JSON_CONVERT : convert; this.primary = idAttr0; + this.primaryOneArray = new Attribute[]{this.primary}; this.aliasmap = aliasmap0; List ddls = new ArrayList<>(); Collections.reverse(ddlList); //父类的字段排在前面 @@ -1046,6 +1055,24 @@ public final class EntityInfo { return t; } + /** + * 根据主键值获取Entity的表名单一元素数组 + * + * @param primary Entity主键值 + * + * @return String[] + */ + public String[] getTableOneArray(Serializable primary) { + if (tableStrategy == null) { + return tableOneArray; + } + String t = tableStrategy.getTable(table, primary); + if (t == null || t.isEmpty()) { + throw new SourceException(table + " tableStrategy.getTable is empty, primary=" + primary); + } + return new String[]{t}; + } + /** * 根据过滤条件获取Entity的表名 * @@ -1091,6 +1118,15 @@ public final class EntityInfo { return this.primary; } + /** + * 获取主键字段的Attribute单一元素数组 + * + * @return Attribute[] + */ + public Attribute[] getPrimaryOneArray() { + return this.primaryOneArray; + } + /** * 遍历数据库表对应的所有字段, 不包含@Transient字段 * diff --git a/src/main/java/org/redkale/util/ResourceFactory.java b/src/main/java/org/redkale/util/ResourceFactory.java index fccda4fca..c7307b970 100644 --- a/src/main/java/org/redkale/util/ResourceFactory.java +++ b/src/main/java/org/redkale/util/ResourceFactory.java @@ -459,6 +459,7 @@ public final class ResourceFactory { /** * 将多个以指定资源名的String对象注入到资源池中 * + * @param 泛型 * @param properties 资源键值对 * @param environmentName 额外的资源名 * @param environmentType 额外的类名