Skip to content

Commit c38c223

Browse files
committed
refactor: 优化对同步操作的支持
1 parent 4a19161 commit c38c223

File tree

9 files changed

+298
-119
lines changed

9 files changed

+298
-119
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.hswebframework.ezorm.rdb.context;
2+
3+
import lombok.SneakyThrows;
4+
import reactor.util.context.Context;
5+
import reactor.util.context.ContextView;
6+
7+
import java.io.Closeable;
8+
import java.lang.reflect.UndeclaredThrowableException;
9+
import java.util.Collections;
10+
import java.util.Comparator;
11+
import java.util.List;
12+
import java.util.ServiceLoader;
13+
import java.util.concurrent.Callable;
14+
import java.util.stream.Collectors;
15+
16+
public class ContextHolder {
17+
18+
private static final List<ContextHolderSupport> supports;
19+
20+
static {
21+
supports = ServiceLoader
22+
.load(ContextHolderSupport.class)
23+
.stream()
24+
.map(ServiceLoader.Provider::get)
25+
.collect(Collectors.toList());
26+
supports.add(new ThreadLocalContextHolderSupport());
27+
supports.sort(Comparator.comparingInt(ContextHolderSupport::order));
28+
}
29+
30+
public static Closeable makeCurrent(ContextView context) {
31+
for (ContextHolderSupport support : supports) {
32+
if (support.isSupport()) {
33+
return support.makeCurrent(context);
34+
}
35+
}
36+
throw new UnsupportedOperationException();
37+
38+
}
39+
40+
@SneakyThrows
41+
public static <T> T doInContext(Context context, Callable<T> call) {
42+
try (Closeable ignore = makeCurrent(context)) {
43+
return call.call();
44+
} catch (UndeclaredThrowableException e) {
45+
throw e.getCause();
46+
}
47+
}
48+
49+
public static Context current() {
50+
for (ContextHolderSupport support : supports) {
51+
if (support.isSupport()) {
52+
return support.current();
53+
}
54+
}
55+
throw new UnsupportedOperationException();
56+
}
57+
58+
public interface ContextHolderSupport {
59+
boolean isSupport();
60+
61+
Closeable makeCurrent(ContextView context);
62+
63+
Context current();
64+
65+
default int order() {
66+
return Integer.MIN_VALUE;
67+
}
68+
}
69+
70+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.hswebframework.ezorm.rdb.context;
2+
3+
import reactor.util.context.Context;
4+
import reactor.util.context.ContextView;
5+
6+
import java.io.Closeable;
7+
8+
/**
9+
* 基于 ThreadLocal 的上下文持有器支持实现
10+
* 适用于传统平台线程环境
11+
*/
12+
public class ThreadLocalContextHolderSupport implements ContextHolder.ContextHolderSupport {
13+
14+
private static final ThreadLocal<Context> contextHolder = ThreadLocal.withInitial(Context::empty);
15+
16+
@Override
17+
public boolean isSupport() {
18+
return true;
19+
}
20+
21+
@Override
22+
public Closeable makeCurrent(ContextView context) {
23+
Context previous = contextHolder.get();
24+
Context newContext = previous.putAll(context);
25+
contextHolder.set(newContext);
26+
27+
return () -> contextHolder.set(previous);
28+
}
29+
30+
@Override
31+
public Context current() {
32+
Context context = contextHolder.get();
33+
return context != null ? context : Context.empty();
34+
}
35+
36+
@Override
37+
public int order() {
38+
return Integer.MAX_VALUE; // 最低优先级,作为回退选项
39+
}
40+
}

hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/executor/jdbc/JdbcSqlExecutor.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import lombok.AllArgsConstructor;
44
import lombok.SneakyThrows;
5+
import org.hswebframework.ezorm.rdb.context.ContextHolder;
56
import org.hswebframework.ezorm.rdb.executor.BatchSqlRequest;
67
import org.hswebframework.ezorm.rdb.executor.DefaultColumnWrapperContext;
78
import org.hswebframework.ezorm.rdb.executor.SqlRequest;
@@ -21,6 +22,10 @@ public abstract class JdbcSqlExecutor {
2122

2223
private Logger logger;
2324

25+
protected Logger logger() {
26+
return ContextHolder.current().getOrDefault(Logger.class, logger);
27+
}
28+
2429
@SneakyThrows
2530
protected void releaseStatement(Statement statement) {
2631
statement.close();
@@ -61,7 +66,7 @@ protected int doUpdate(Logger logger, Connection connection, SqlRequest request)
6166
}
6267
}
6368
return count;
64-
}catch (Throwable e) {
69+
} catch (Throwable e) {
6570
logger.error("==> Error: {}", request.toNativeSql(), e);
6671
throw e;
6772
} finally {
@@ -72,7 +77,7 @@ protected int doUpdate(Logger logger, Connection connection, SqlRequest request)
7277
}
7378

7479
protected int doUpdate(Connection connection, SqlRequest request) {
75-
return doUpdate(logger, connection, request);
80+
return doUpdate(logger(), connection, request);
7681
}
7782

7883
@SneakyThrows
@@ -110,7 +115,7 @@ protected void doExecute(Logger logger, Connection connection, SqlRequest reques
110115
}
111116

112117
protected void doExecute(Connection connection, SqlRequest request) {
113-
doExecute(logger, connection, request);
118+
doExecute(logger(), connection, request);
114119
}
115120

116121
@SneakyThrows
@@ -207,6 +212,6 @@ protected <T, R> R doSelect(Logger logger,
207212

208213
@SneakyThrows
209214
public <T, R> R doSelect(Connection connection, SqlRequest request, ResultWrapper<T, R> wrapper) {
210-
return doSelect(logger, connection, request, wrapper, Disposables.composite());
215+
return doSelect(logger(), connection, request, wrapper, Disposables.composite());
211216
}
212217
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package org.hswebframework.ezorm.rdb.mapping.defaults;
22

3+
import org.hswebframework.ezorm.rdb.context.ContextHolder;
34
import org.hswebframework.ezorm.rdb.mapping.SyncDelete;
45
import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata;
56
import org.hswebframework.ezorm.rdb.operator.dml.delete.DeleteOperator;
7+
import reactor.util.context.Context;
68

79
public class DefaultSyncDelete extends DefaultDelete<SyncDelete> implements SyncDelete {
810

9-
public DefaultSyncDelete(RDBTableMetadata table, DeleteOperator operator) {
10-
super(table,operator);
11+
private final Context context;
12+
13+
public DefaultSyncDelete(RDBTableMetadata table, DeleteOperator operator, Context context) {
14+
super(table, operator);
15+
this.context = context;
1116
}
1217

1318
@Override
1419
public int execute() {
15-
return doExecute().sync();
20+
return ContextHolder.doInContext(context, () -> doExecute().sync());
1621
}
1722
}

hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/mapping/defaults/DefaultSyncQuery.java

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.hswebframework.ezorm.rdb.mapping.defaults;
22

3+
import org.hswebframework.ezorm.rdb.context.ContextHolder;
34
import org.hswebframework.ezorm.rdb.executor.wrapper.ResultWrapper;
45
import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping;
56
import org.hswebframework.ezorm.rdb.mapping.SyncQuery;
67
import org.hswebframework.ezorm.rdb.mapping.events.MappingEventTypes;
78
import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata;
89
import org.hswebframework.ezorm.rdb.operator.DMLOperator;
10+
import reactor.util.context.Context;
911

1012
import java.util.List;
1113
import java.util.Optional;
@@ -18,75 +20,94 @@
1820

1921
public class DefaultSyncQuery<T> extends DefaultQuery<T, SyncQuery<T>> implements SyncQuery<T> {
2022

21-
public DefaultSyncQuery(TableOrViewMetadata tableMetadata, EntityColumnMapping mapping, DMLOperator operator, ResultWrapper<T, ?> wrapper) {
23+
private final Context context;
24+
25+
public DefaultSyncQuery(TableOrViewMetadata tableMetadata,
26+
EntityColumnMapping mapping,
27+
DMLOperator operator,
28+
ResultWrapper<T, ?> wrapper,
29+
Context context) {
2230
super(tableMetadata, mapping, operator, wrapper);
31+
this.context = context;
2332
}
2433

2534
@Override
2635
public List<T> fetch() {
36+
return ContextHolder.doInContext(context,this::fetch0);
37+
}
38+
39+
public List<T> fetch0() {
2740
return operator
28-
.query(tableMetadata)
29-
.context(param.getContext())
30-
.select(getSelectColumn())
31-
.selectExcludes(param.getExcludes())
32-
.where(param.getTerms())
33-
.orderBy(getSortOrder())
34-
.when(param.isPaging(), query -> query.paging(param.getPageIndex(), param.getPageSize()))
35-
.accept(queryOperator ->
41+
.query(tableMetadata)
42+
.context(param.getContext())
43+
.select(getSelectColumn())
44+
.selectExcludes(param.getExcludes())
45+
.where(param.getTerms())
46+
.orderBy(getSortOrder())
47+
.when(param.isPaging(), query -> query.paging(param.getPageIndex(), param.getPageSize()))
48+
.accept(queryOperator ->
3649
tableMetadata.fireEvent(MappingEventTypes.select_before, eventContext ->
37-
eventContext.set(
38-
source(DefaultSyncQuery.this),
39-
query(queryOperator),
40-
dml(operator),
41-
executorType("sync"),
42-
type("fetch")
43-
)))
44-
.fetch(eventWrapper(tableMetadata, list(wrapper), executorType("sync"), type("fetch")))
45-
.sync();
50+
eventContext.set(
51+
source(DefaultSyncQuery.this),
52+
query(queryOperator),
53+
dml(operator),
54+
executorType("sync"),
55+
type("fetch")
56+
)))
57+
.fetch(eventWrapper(tableMetadata, list(wrapper), executorType("sync"), type("fetch")))
58+
.sync();
4659
}
4760

4861
@Override
4962
public Optional<T> fetchOne() {
63+
return ContextHolder.doInContext(context,this::fetchOne0);
64+
}
65+
66+
public Optional<T> fetchOne0() {
5067
return operator
51-
.query(tableMetadata)
52-
.context(param.getContext())
53-
.select(getSelectColumn())
54-
.where(param.getTerms())
55-
.orderBy(getSortOrder())
56-
.paging(0, 1)
57-
.accept(queryOperator ->
68+
.query(tableMetadata)
69+
.context(param.getContext())
70+
.select(getSelectColumn())
71+
.where(param.getTerms())
72+
.orderBy(getSortOrder())
73+
.paging(0, 1)
74+
.accept(queryOperator ->
5875
tableMetadata.fireEvent(
59-
MappingEventTypes.select_before,
60-
source(DefaultSyncQuery.this),
61-
query(queryOperator),
62-
dml(operator),
63-
executorType("sync"),
64-
type("fetchOne")
76+
MappingEventTypes.select_before,
77+
source(DefaultSyncQuery.this),
78+
query(queryOperator),
79+
dml(operator),
80+
executorType("sync"),
81+
type("fetchOne")
6582
))
66-
.fetch(eventWrapper(tableMetadata, optional(single(wrapper)), executorType("sync"), type("fetchOne")))
67-
.sync();
83+
.fetch(eventWrapper(tableMetadata, optional(single(wrapper)), executorType("sync"), type("fetchOne")))
84+
.sync();
6885
}
6986

7087
@Override
7188
public int count() {
89+
return ContextHolder.doInContext(context,this::count0);
90+
}
91+
92+
public int count0() {
7293
return operator
73-
.query(tableMetadata)
74-
.context(param.getContext())
75-
.select(count1().as("_total"))
76-
.where(param.getTerms())
77-
.accept(queryOperator ->
94+
.query(tableMetadata)
95+
.context(param.getContext())
96+
.select(count1().as("_total"))
97+
.where(param.getTerms())
98+
.accept(queryOperator ->
7899
tableMetadata.fireEvent(
79-
MappingEventTypes.select_before,
80-
source(DefaultSyncQuery.this),
81-
query(queryOperator),
82-
dml(operator),
83-
executorType("sync"),
84-
type("count")
100+
MappingEventTypes.select_before,
101+
source(DefaultSyncQuery.this),
102+
query(queryOperator),
103+
dml(operator),
104+
executorType("sync"),
105+
type("count")
85106
))
86-
.fetch(optional(single(column("_total", Number.class::cast))))
87-
.sync()
88-
.map(Number::intValue)
89-
.orElse(0);
107+
.fetch(optional(single(column("_total", Number.class::cast))))
108+
.sync()
109+
.map(Number::intValue)
110+
.orElse(0);
90111
}
91112

92113

0 commit comments

Comments
 (0)