Skip to content

Commit 95f3fa9

Browse files
committed
Support "mappedColumn" on insert statements
We added a "javaProperty" to SqlColumn so properties can be centrally configured, and then used on generated insert statements. This will make the mappers generated from MyBatis Generator less verbose.
1 parent f0047f6 commit 95f3fa9

18 files changed

+360
-33
lines changed

src/main/java/org/mybatis/dynamic/sql/SqlColumn.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class SqlColumn<T> implements BindableColumn<T>, SortSpecification {
3737
protected final ParameterTypeConverter<T, ?> parameterTypeConverter;
3838
protected final @Nullable String tableQualifier;
3939
protected final @Nullable Class<T> javaType;
40+
protected final @Nullable String javaProperty;
4041

4142
private SqlColumn(Builder<T> builder) {
4243
name = Objects.requireNonNull(builder.name);
@@ -49,6 +50,7 @@ private SqlColumn(Builder<T> builder) {
4950
parameterTypeConverter = Objects.requireNonNull(builder.parameterTypeConverter);
5051
tableQualifier = builder.tableQualifier;
5152
javaType = builder.javaType;
53+
javaProperty = builder.javaProperty;
5254
}
5355

5456
public String name() {
@@ -79,6 +81,10 @@ public Optional<Class<T>> javaType() {
7981
return Optional.ofNullable(javaType);
8082
}
8183

84+
public Optional<String> javaProperty() {
85+
return Optional.ofNullable(javaProperty);
86+
}
87+
8288
@Override
8389
public @Nullable Object convertParameterType(@Nullable T value) {
8490
return value == null ? null : parameterTypeConverter.convert(value);
@@ -164,6 +170,11 @@ public <S> SqlColumn<S> withJavaType(Class<S> javaType) {
164170
return b.withJavaType(javaType).build();
165171
}
166172

173+
public <S> SqlColumn<S> withJavaProperty(String javaProperty) {
174+
Builder<S> b = copy();
175+
return b.withJavaProperty(javaProperty).build();
176+
}
177+
167178
/**
168179
* This method helps us tell a bit of fiction to the Java compiler. Java, for better or worse,
169180
* does not carry generic type information through chained methods. We want to enable method
@@ -185,7 +196,8 @@ private <S> Builder<S> copy() {
185196
.withRenderingStrategy(this.renderingStrategy)
186197
.withParameterTypeConverter((ParameterTypeConverter<S, ?>) this.parameterTypeConverter)
187198
.withTableQualifier(this.tableQualifier)
188-
.withJavaType((Class<S>) this.javaType);
199+
.withJavaType((Class<S>) this.javaType)
200+
.withJavaProperty(this.javaProperty);
189201
}
190202

191203
public static <T> SqlColumn<T> of(String name, SqlTable table) {
@@ -212,6 +224,7 @@ public static class Builder<T> {
212224
protected ParameterTypeConverter<T, ?> parameterTypeConverter = v -> v;
213225
protected @Nullable String tableQualifier;
214226
protected @Nullable Class<T> javaType;
227+
protected @Nullable String javaProperty;
215228

216229
public Builder<T> withName(String name) {
217230
this.name = name;
@@ -263,6 +276,11 @@ public Builder<T> withJavaType(@Nullable Class<T> javaType) {
263276
return this;
264277
}
265278

279+
public Builder<T> withJavaProperty(@Nullable String javaProperty) {
280+
this.javaProperty = javaProperty;
281+
return this;
282+
}
283+
266284
public SqlColumn<T> build() {
267285
return new SqlColumn<>(this);
268286
}

src/main/java/org/mybatis/dynamic/sql/insert/InsertDSL.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.mybatis.dynamic.sql.util.AbstractColumnMapping;
2828
import org.mybatis.dynamic.sql.util.Buildable;
2929
import org.mybatis.dynamic.sql.util.ConstantMapping;
30+
import org.mybatis.dynamic.sql.util.MappedColumnMapping;
31+
import org.mybatis.dynamic.sql.util.MappedColumnWhenPresentMapping;
3032
import org.mybatis.dynamic.sql.util.NullMapping;
3133
import org.mybatis.dynamic.sql.util.PropertyMapping;
3234
import org.mybatis.dynamic.sql.util.PropertyWhenPresentMapping;
@@ -49,6 +51,16 @@ public <F> ColumnMappingFinisher<F> map(SqlColumn<F> column) {
4951
return new ColumnMappingFinisher<>(column);
5052
}
5153

54+
public <F> InsertDSL<T> withMappedColumn(SqlColumn<F> column) {
55+
columnMappings.add(MappedColumnMapping.of(column));
56+
return this;
57+
}
58+
59+
public <F> InsertDSL<T> withMappedColumnWhenPresent(SqlColumn<F> column, Supplier<?> valueSupplier) {
60+
columnMappings.add(MappedColumnWhenPresentMapping.of(column, valueSupplier));
61+
return this;
62+
}
63+
5264
@Override
5365
public InsertModel<T> build() {
5466
return InsertModel.withRow(row)

src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.mybatis.dynamic.sql.util.AbstractColumnMapping;
2626
import org.mybatis.dynamic.sql.util.Buildable;
2727
import org.mybatis.dynamic.sql.util.ConstantMapping;
28+
import org.mybatis.dynamic.sql.util.MappedColumnMapping;
2829
import org.mybatis.dynamic.sql.util.NullMapping;
2930
import org.mybatis.dynamic.sql.util.PropertyMapping;
3031
import org.mybatis.dynamic.sql.util.RowMapping;
@@ -46,6 +47,11 @@ public <F> ColumnMappingFinisher<F> map(SqlColumn<F> column) {
4647
return new ColumnMappingFinisher<>(column);
4748
}
4849

50+
public <F> MultiRowInsertDSL<T> withMappedColumn(SqlColumn<F> column) {
51+
columnMappings.add(MappedColumnMapping.of(column));
52+
return this;
53+
}
54+
4955
@Override
5056
public MultiRowInsertModel<T> build() {
5157
return MultiRowInsertModel.withRecords(records)

src/main/java/org/mybatis/dynamic/sql/insert/render/MultiRowValuePhraseVisitor.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
package org.mybatis.dynamic.sql.insert.render;
1717

1818
import org.mybatis.dynamic.sql.SqlColumn;
19+
import org.mybatis.dynamic.sql.exception.InvalidSqlException;
1920
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2021
import org.mybatis.dynamic.sql.util.ConstantMapping;
22+
import org.mybatis.dynamic.sql.util.MappedColumnMapping;
23+
import org.mybatis.dynamic.sql.util.Messages;
2124
import org.mybatis.dynamic.sql.util.MultiRowInsertMappingVisitor;
2225
import org.mybatis.dynamic.sql.util.NullMapping;
2326
import org.mybatis.dynamic.sql.util.PropertyMapping;
@@ -69,6 +72,22 @@ public FieldAndValueAndParameters visit(RowMapping mapping) {
6972
.build();
7073
}
7174

75+
@Override
76+
public FieldAndValueAndParameters visit(MappedColumnMapping mapping) {
77+
return FieldAndValueAndParameters.withFieldName(mapping.columnName())
78+
.withValuePhrase(calculateJdbcPlaceholder(
79+
mapping.column(),
80+
getMappedPropertyName(mapping.column()))
81+
)
82+
.build();
83+
}
84+
85+
private String getMappedPropertyName(SqlColumn<?> column) {
86+
return column.javaProperty().orElseThrow(() ->
87+
new InvalidSqlException(Messages
88+
.getString("ERROR.50", column.name()))); //$NON-NLS-1$
89+
}
90+
7291
private String calculateJdbcPlaceholder(SqlColumn<?> column) {
7392
return column.renderingStrategy().orElse(renderingStrategy).getRecordBasedInsertBinding(column, prefix);
7493
}

src/main/java/org/mybatis/dynamic/sql/insert/render/ValuePhraseVisitor.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
import java.util.Optional;
1919

2020
import org.mybatis.dynamic.sql.SqlColumn;
21+
import org.mybatis.dynamic.sql.exception.InvalidSqlException;
2122
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2223
import org.mybatis.dynamic.sql.util.ConstantMapping;
2324
import org.mybatis.dynamic.sql.util.InsertMappingVisitor;
25+
import org.mybatis.dynamic.sql.util.MappedColumnMapping;
26+
import org.mybatis.dynamic.sql.util.MappedColumnWhenPresentMapping;
27+
import org.mybatis.dynamic.sql.util.Messages;
2428
import org.mybatis.dynamic.sql.util.NullMapping;
2529
import org.mybatis.dynamic.sql.util.PropertyMapping;
2630
import org.mybatis.dynamic.sql.util.PropertyWhenPresentMapping;
@@ -80,6 +84,31 @@ public Optional<FieldAndValueAndParameters> visit(RowMapping mapping) {
8084
.buildOptional();
8185
}
8286

87+
@Override
88+
public Optional<FieldAndValueAndParameters> visit(MappedColumnMapping mapping) {
89+
return FieldAndValueAndParameters.withFieldName(mapping.columnName())
90+
.withValuePhrase(calculateJdbcPlaceholder(
91+
mapping.column(),
92+
getMappedPropertyName(mapping.column()))
93+
)
94+
.buildOptional();
95+
}
96+
97+
@Override
98+
public Optional<FieldAndValueAndParameters> visit(MappedColumnWhenPresentMapping mapping) {
99+
if (mapping.shouldRender()) {
100+
return visit((MappedColumnMapping) mapping);
101+
} else {
102+
return Optional.empty();
103+
}
104+
}
105+
106+
private String getMappedPropertyName(SqlColumn<?> column) {
107+
return column.javaProperty().orElseThrow(() ->
108+
new InvalidSqlException(Messages
109+
.getString("ERROR.50", column.name()))); //$NON-NLS-1$
110+
}
111+
83112
private String calculateJdbcPlaceholder(SqlColumn<?> column) {
84113
return column.renderingStrategy().orElse(renderingStrategy)
85114
.getRecordBasedInsertBinding(column, "row"); //$NON-NLS-1$

src/main/java/org/mybatis/dynamic/sql/util/ColumnMappingVisitor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,8 @@ public interface ColumnMappingVisitor<R> {
5252
R visit(ColumnToColumnMapping mapping);
5353

5454
R visit(RowMapping mapping);
55+
56+
R visit(MappedColumnMapping mapping);
57+
58+
R visit(MappedColumnWhenPresentMapping mapping);
5559
}

src/main/java/org/mybatis/dynamic/sql/util/GeneralInsertMappingVisitor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,14 @@ public final R visit(ColumnToColumnMapping columnMapping) {
4040
public final R visit(RowMapping mapping) {
4141
throw new UnsupportedOperationException(Messages.getInternalErrorString(InternalError.INTERNAL_ERROR_14));
4242
}
43+
44+
@Override
45+
public R visit(MappedColumnMapping mapping) {
46+
throw new UnsupportedOperationException(Messages.getInternalErrorString(InternalError.INTERNAL_ERROR_16));
47+
}
48+
49+
@Override
50+
public R visit(MappedColumnWhenPresentMapping mapping) {
51+
throw new UnsupportedOperationException(Messages.getInternalErrorString(InternalError.INTERNAL_ERROR_17));
52+
}
4353
}

src/main/java/org/mybatis/dynamic/sql/util/InternalError.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ public enum InternalError {
3333
INTERNAL_ERROR_12(12),
3434
INTERNAL_ERROR_13(13),
3535
INTERNAL_ERROR_14(14),
36-
INTERNAL_ERROR_15(15);
36+
INTERNAL_ERROR_15(15),
37+
INTERNAL_ERROR_16(16),
38+
INTERNAL_ERROR_17(17),
39+
INTERNAL_ERROR_18(18),
40+
INTERNAL_ERROR_19(19),
41+
INTERNAL_ERROR_20(20);
3742

3843
private final int number;
3944

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2016-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.util;
17+
18+
import org.mybatis.dynamic.sql.SqlColumn;
19+
20+
public class MappedColumnMapping extends AbstractColumnMapping {
21+
22+
protected MappedColumnMapping(SqlColumn<?> column) {
23+
super(column);
24+
}
25+
26+
@Override
27+
public <R> R accept(ColumnMappingVisitor<R> visitor) {
28+
return visitor.visit(this);
29+
}
30+
31+
public static MappedColumnMapping of(SqlColumn<?> column) {
32+
return new MappedColumnMapping(column);
33+
}
34+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2016-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.dynamic.sql.util;
17+
18+
import org.mybatis.dynamic.sql.SqlColumn;
19+
20+
import java.util.Objects;
21+
import java.util.function.Supplier;
22+
23+
public class MappedColumnWhenPresentMapping extends MappedColumnMapping {
24+
private final Supplier<?> valueSupplier;
25+
26+
private MappedColumnWhenPresentMapping(SqlColumn<?> column, Supplier<?> valueSupplier) {
27+
super(column);
28+
this.valueSupplier = Objects.requireNonNull(valueSupplier);
29+
}
30+
31+
public boolean shouldRender() {
32+
return valueSupplier.get() != null;
33+
}
34+
35+
@Override
36+
public <R> R accept(ColumnMappingVisitor<R> visitor) {
37+
return visitor.visit(this);
38+
}
39+
40+
public static MappedColumnWhenPresentMapping of(SqlColumn<?> column, Supplier<?> valueSupplier) {
41+
return new MappedColumnWhenPresentMapping(column, valueSupplier);
42+
}
43+
}

0 commit comments

Comments
 (0)