Skip to content

Commit 229cfe0

Browse files
committed
Refactor mapping logic by introducing MappingSupport class
Centralized column mapping functionality into a new MappingSupport class, reducing duplication and improving maintainability. Updated corresponding classes (EntityProvider, LinkableEntityPoolProvider) to use this new utility. Deprecated old methods and added unit test adjustments for the changes.
1 parent 3520e52 commit 229cfe0

File tree

4 files changed

+236
-145
lines changed

4 files changed

+236
-145
lines changed

doma-core/src/main/java/org/seasar/doma/internal/jdbc/command/EntityProvider.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.List;
2828
import java.util.Map;
2929
import java.util.Set;
30+
import java.util.stream.Collectors;
3031
import org.seasar.doma.jdbc.DuplicateColumnHandler;
3132
import org.seasar.doma.jdbc.JdbcMappingVisitor;
3233
import org.seasar.doma.jdbc.Naming;
@@ -52,6 +53,8 @@ public class EntityProvider<ENTITY> extends AbstractObjectProvider<ENTITY> {
5253

5354
protected final DuplicateColumnHandler duplicateColumnHandler;
5455

56+
private final MappingSupport mappingSupport;
57+
5558
protected Map<Integer, EntityPropertyType<ENTITY, ?>> indexMap;
5659

5760
public EntityProvider(EntityType<ENTITY> entityType, Query query, boolean resultMappingEnsured) {
@@ -62,6 +65,9 @@ public EntityProvider(EntityType<ENTITY> entityType, Query query, boolean result
6265
this.jdbcMappingVisitor = query.getConfig().getDialect().getJdbcMappingVisitor();
6366
this.unknownColumnHandler = query.getConfig().getUnknownColumnHandler();
6467
this.duplicateColumnHandler = query.getConfig().getDuplicateColumnHandler();
68+
this.mappingSupport =
69+
new MappingSupport(
70+
entityType, query, resultMappingEnsured, unknownColumnHandler, duplicateColumnHandler);
6571
}
6672

6773
@Override
@@ -72,7 +78,7 @@ public ENTITY get(ResultSet resultSet) throws SQLException {
7278
protected ENTITY build(ResultSet resultSet) throws SQLException {
7379
assertNotNull(resultSet);
7480
if (indexMap == null) {
75-
indexMap = createIndexMap(resultSet.getMetaData(), entityType);
81+
indexMap = createIndexMap(resultSet.getMetaData());
7682
}
7783
Map<String, Property<ENTITY, ?>> states = new HashMap<>(indexMap.size());
7884
for (Map.Entry<Integer, EntityPropertyType<ENTITY, ?>> entry : indexMap.entrySet()) {
@@ -89,6 +95,7 @@ protected ENTITY build(ResultSet resultSet) throws SQLException {
8995
return entity;
9096
}
9197

98+
@Deprecated(forRemoval = true)
9299
protected HashMap<Integer, EntityPropertyType<ENTITY, ?>> createIndexMap(
93100
ResultSetMetaData resultSetMeta, EntityType<ENTITY> entityType) throws SQLException {
94101
HashMap<Integer, EntityPropertyType<ENTITY, ?>> indexMap = new HashMap<>();
@@ -120,6 +127,19 @@ protected ENTITY build(ResultSet resultSet) throws SQLException {
120127
return indexMap;
121128
}
122129

130+
@SuppressWarnings("unchecked")
131+
private Map<Integer, EntityPropertyType<ENTITY, ?>> createIndexMap(
132+
ResultSetMetaData resultSetMeta) throws SQLException {
133+
Map<String, MappingSupport.PropType> columnNameMap = createColumnNameMap();
134+
return indexMap =
135+
mappingSupport.createIndexMap(resultSetMeta, columnNameMap).entrySet().stream()
136+
.collect(
137+
Collectors.toMap(
138+
Map.Entry::getKey,
139+
e -> (EntityPropertyType<ENTITY, ?>) e.getValue().propertyType()));
140+
}
141+
142+
@Deprecated
123143
protected HashMap<String, EntityPropertyType<ENTITY, ?>> createColumnNameMap(
124144
EntityType<ENTITY> entityType) {
125145
Naming naming = query.getConfig().getNaming();
@@ -132,6 +152,19 @@ protected ENTITY build(ResultSet resultSet) throws SQLException {
132152
return result;
133153
}
134154

155+
private HashMap<String, MappingSupport.PropType> createColumnNameMap() {
156+
Naming naming = query.getConfig().getNaming();
157+
List<EntityPropertyType<ENTITY, ?>> propertyTypes = entityType.getEntityPropertyTypes();
158+
HashMap<String, MappingSupport.PropType> result = new HashMap<>(propertyTypes.size());
159+
for (EntityPropertyType<ENTITY, ?> propertyType : propertyTypes) {
160+
String columnName = propertyType.getColumnName(naming::apply);
161+
result.put(
162+
columnName.toLowerCase(), new MappingSupport.PropType(entityType, propertyType, ""));
163+
}
164+
return result;
165+
}
166+
167+
@Deprecated(forRemoval = true)
135168
protected void throwResultMappingException(
136169
Set<EntityPropertyType<ENTITY, ?>> unmappedPropertySet) {
137170
Naming naming = query.getConfig().getNaming();
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright Doma 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.seasar.doma.internal.jdbc.command;
17+
18+
import static org.seasar.doma.internal.Constants.ROWNUMBER_COLUMN_NAME;
19+
20+
import java.sql.ResultSetMetaData;
21+
import java.sql.SQLException;
22+
import java.util.ArrayList;
23+
import java.util.HashMap;
24+
import java.util.HashSet;
25+
import java.util.Iterator;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Objects;
29+
import java.util.Set;
30+
import java.util.function.BiFunction;
31+
import org.seasar.doma.jdbc.DuplicateColumnHandler;
32+
import org.seasar.doma.jdbc.Naming;
33+
import org.seasar.doma.jdbc.ResultMappingException;
34+
import org.seasar.doma.jdbc.Sql;
35+
import org.seasar.doma.jdbc.UnknownColumnHandler;
36+
import org.seasar.doma.jdbc.entity.EntityPropertyType;
37+
import org.seasar.doma.jdbc.entity.EntityType;
38+
import org.seasar.doma.jdbc.entity.NamingType;
39+
import org.seasar.doma.jdbc.entity.Property;
40+
import org.seasar.doma.jdbc.query.Query;
41+
import org.seasar.doma.wrapper.Wrapper;
42+
43+
public class MappingSupport {
44+
45+
private final EntityType<?> entityType;
46+
private final Query query;
47+
private final boolean resultMappingEnsured;
48+
private final UnknownColumnHandler unknownColumnHandler;
49+
private final DuplicateColumnHandler duplicateColumnHandler;
50+
51+
public MappingSupport(
52+
EntityType<?> entityType,
53+
Query query,
54+
boolean resultMappingEnsured,
55+
UnknownColumnHandler unknownColumnHandler,
56+
DuplicateColumnHandler duplicateColumnHandler) {
57+
this.entityType = Objects.requireNonNull(entityType);
58+
this.query = Objects.requireNonNull(query);
59+
this.resultMappingEnsured = resultMappingEnsured;
60+
this.unknownColumnHandler = Objects.requireNonNull(unknownColumnHandler);
61+
this.duplicateColumnHandler = Objects.requireNonNull(duplicateColumnHandler);
62+
}
63+
64+
public Map<Integer, MappingSupport.PropType> createIndexMap(
65+
ResultSetMetaData resultSetMeta, Map<String, PropType> columnNameMap) throws SQLException {
66+
HashMap<Integer, PropType> indexMap = new HashMap<>();
67+
Set<PropType> unmappedPropertySet =
68+
resultMappingEnsured ? new HashSet<>(columnNameMap.values()) : new HashSet<>();
69+
Set<String> seenColumnNames = new HashSet<>();
70+
int count = resultSetMeta.getColumnCount();
71+
for (int i = 1; i < count + 1; i++) {
72+
String columnName = resultSetMeta.getColumnLabel(i);
73+
String lowerCaseColumnName = columnName.toLowerCase();
74+
if (!seenColumnNames.add(lowerCaseColumnName)) {
75+
duplicateColumnHandler.handle(query, lowerCaseColumnName);
76+
}
77+
PropType propertyType = columnNameMap.get(lowerCaseColumnName);
78+
if (propertyType == null) {
79+
if (ROWNUMBER_COLUMN_NAME.equals(lowerCaseColumnName)) {
80+
continue;
81+
}
82+
unknownColumnHandler.handle(query, entityType, lowerCaseColumnName);
83+
} else {
84+
unmappedPropertySet.remove(propertyType);
85+
indexMap.put(i, propertyType);
86+
}
87+
}
88+
if (resultMappingEnsured && !unmappedPropertySet.isEmpty()) {
89+
throwResultMappingException(unmappedPropertySet);
90+
}
91+
return indexMap;
92+
}
93+
94+
private void throwResultMappingException(Set<PropType> unmappedPropertySet) {
95+
Naming naming = query.getConfig().getNaming();
96+
int size = unmappedPropertySet.size();
97+
List<String> unmappedPropertyNames = new ArrayList<>(size);
98+
List<String> expectedColumnNames = new ArrayList<>(size);
99+
for (PropType propType : unmappedPropertySet) {
100+
unmappedPropertyNames.add(propType.name());
101+
expectedColumnNames.add(propType.columnName(naming::apply));
102+
}
103+
Class<?> entityClass;
104+
Iterator<PropType> iterator = unmappedPropertySet.iterator();
105+
if (iterator.hasNext()) {
106+
entityClass = iterator.next().entityType().getEntityClass();
107+
} else {
108+
entityClass = this.entityType.getEntityClass();
109+
}
110+
Sql<?> sql = query.getSql();
111+
throw new ResultMappingException(
112+
query.getConfig().getExceptionSqlLogType(),
113+
entityClass.getName(),
114+
unmappedPropertyNames,
115+
expectedColumnNames,
116+
sql.getKind(),
117+
sql.getRawSql(),
118+
sql.getFormattedSql(),
119+
sql.getSqlFilePath());
120+
}
121+
122+
public record PropType(
123+
EntityType<?> entityType, EntityPropertyType<?, ?> propertyType, String propertyPath) {
124+
public String name() {
125+
return propertyType.getName();
126+
}
127+
128+
public String columnName(BiFunction<NamingType, String, String> namingFunction) {
129+
return propertyType.getColumnName(namingFunction);
130+
}
131+
}
132+
133+
public record Prop(PropType propType, Property<Object, ?> property, Object rawValue) {
134+
135+
public EntityType<?> entityType() {
136+
return propType.entityType();
137+
}
138+
139+
public String propertyPath() {
140+
return propType.propertyPath();
141+
}
142+
143+
public String name() {
144+
return propType.propertyType().getName();
145+
}
146+
147+
public boolean isId() {
148+
return propType.propertyType().isId();
149+
}
150+
151+
public Wrapper<?> wrapper() {
152+
return property.getWrapper();
153+
}
154+
}
155+
}

0 commit comments

Comments
 (0)