1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.generator.internal.types;
17
18 import static org.mybatis.generator.internal.util.StringUtility.isTrue;
19
20 import java.math.BigDecimal;
21 import java.sql.Types;
22 import java.time.LocalDate;
23 import java.time.LocalDateTime;
24 import java.time.LocalTime;
25 import java.time.OffsetDateTime;
26 import java.time.OffsetTime;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Optional;
31 import java.util.Properties;
32
33 import org.jspecify.annotations.Nullable;
34 import org.mybatis.generator.api.IntrospectedColumn;
35 import org.mybatis.generator.api.JavaTypeResolver;
36 import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
37 import org.mybatis.generator.config.Context;
38 import org.mybatis.generator.config.PropertyRegistry;
39
40 public class JavaTypeResolverDefaultImpl implements JavaTypeResolver {
41
42 protected @Nullable List<String> warnings;
43
44 protected final Properties properties;
45
46 protected @Nullable Context context;
47
48 protected boolean forceBigDecimals;
49
50 protected final Map<Integer, JdbcTypeInformation> typeMap;
51
52 public JavaTypeResolverDefaultImpl() {
53 super();
54 properties = new Properties();
55 typeMap = new HashMap<>();
56
57 typeMap.put(Types.ARRAY, new JdbcTypeInformation("ARRAY",
58 new FullyQualifiedJavaType(Object.class.getName())));
59 typeMap.put(Types.BIGINT, new JdbcTypeInformation("BIGINT",
60 new FullyQualifiedJavaType(Long.class.getName())));
61 typeMap.put(Types.BINARY, new JdbcTypeInformation("BINARY",
62 new FullyQualifiedJavaType("byte[]")));
63 typeMap.put(Types.BIT, new JdbcTypeInformation("BIT",
64 new FullyQualifiedJavaType(Boolean.class.getName())));
65 typeMap.put(Types.BLOB, new JdbcTypeInformation("BLOB",
66 new FullyQualifiedJavaType("byte[]")));
67 typeMap.put(Types.BOOLEAN, new JdbcTypeInformation("BOOLEAN",
68 new FullyQualifiedJavaType(Boolean.class.getName())));
69 typeMap.put(Types.CHAR, new JdbcTypeInformation("CHAR",
70 new FullyQualifiedJavaType(String.class.getName())));
71 typeMap.put(Types.CLOB, new JdbcTypeInformation("CLOB",
72 new FullyQualifiedJavaType(String.class.getName())));
73 typeMap.put(Types.DATALINK, new JdbcTypeInformation("DATALINK",
74 new FullyQualifiedJavaType(Object.class.getName())));
75 typeMap.put(Types.DATE, new JdbcTypeInformation("DATE",
76 new FullyQualifiedJavaType(LocalDate.class.getName())));
77 typeMap.put(Types.DECIMAL, new JdbcTypeInformation("DECIMAL",
78 new FullyQualifiedJavaType(BigDecimal.class.getName())));
79 typeMap.put(Types.DISTINCT, new JdbcTypeInformation("DISTINCT",
80 new FullyQualifiedJavaType(Object.class.getName())));
81 typeMap.put(Types.DOUBLE, new JdbcTypeInformation("DOUBLE",
82 new FullyQualifiedJavaType(Double.class.getName())));
83 typeMap.put(Types.FLOAT, new JdbcTypeInformation("FLOAT",
84 new FullyQualifiedJavaType(Double.class.getName())));
85 typeMap.put(Types.INTEGER, new JdbcTypeInformation("INTEGER",
86 new FullyQualifiedJavaType(Integer.class.getName())));
87 typeMap.put(Types.JAVA_OBJECT, new JdbcTypeInformation("JAVA_OBJECT",
88 new FullyQualifiedJavaType(Object.class.getName())));
89 typeMap.put(Types.LONGNVARCHAR, new JdbcTypeInformation("LONGNVARCHAR",
90 new FullyQualifiedJavaType(String.class.getName())));
91 typeMap.put(Types.LONGVARBINARY, new JdbcTypeInformation("LONGVARBINARY",
92 new FullyQualifiedJavaType("byte[]")));
93 typeMap.put(Types.LONGVARCHAR, new JdbcTypeInformation("LONGVARCHAR",
94 new FullyQualifiedJavaType(String.class.getName())));
95 typeMap.put(Types.NCHAR, new JdbcTypeInformation("NCHAR",
96 new FullyQualifiedJavaType(String.class.getName())));
97 typeMap.put(Types.NCLOB, new JdbcTypeInformation("NCLOB",
98 new FullyQualifiedJavaType(String.class.getName())));
99 typeMap.put(Types.NVARCHAR, new JdbcTypeInformation("NVARCHAR",
100 new FullyQualifiedJavaType(String.class.getName())));
101 typeMap.put(Types.NULL, new JdbcTypeInformation("NULL",
102 new FullyQualifiedJavaType(Object.class.getName())));
103 typeMap.put(Types.NUMERIC, new JdbcTypeInformation("NUMERIC",
104 new FullyQualifiedJavaType(BigDecimal.class.getName())));
105 typeMap.put(Types.OTHER, new JdbcTypeInformation("OTHER",
106 new FullyQualifiedJavaType(Object.class.getName())));
107 typeMap.put(Types.REAL, new JdbcTypeInformation("REAL",
108 new FullyQualifiedJavaType(Float.class.getName())));
109 typeMap.put(Types.REF, new JdbcTypeInformation("REF",
110 new FullyQualifiedJavaType(Object.class.getName())));
111 typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT",
112 new FullyQualifiedJavaType(Short.class.getName())));
113 typeMap.put(Types.SQLXML, new JdbcTypeInformation("SQLXML",
114 new FullyQualifiedJavaType(String.class.getName())));
115 typeMap.put(Types.STRUCT, new JdbcTypeInformation("STRUCT",
116 new FullyQualifiedJavaType(Object.class.getName())));
117 typeMap.put(Types.TIME, new JdbcTypeInformation("TIME",
118 new FullyQualifiedJavaType(LocalTime.class.getName())));
119 typeMap.put(Types.TIMESTAMP, new JdbcTypeInformation("TIMESTAMP",
120 new FullyQualifiedJavaType(LocalDateTime.class.getName())));
121 typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT",
122 new FullyQualifiedJavaType(Byte.class.getName())));
123 typeMap.put(Types.VARBINARY, new JdbcTypeInformation("VARBINARY",
124 new FullyQualifiedJavaType("byte[]")));
125 typeMap.put(Types.VARCHAR, new JdbcTypeInformation("VARCHAR",
126 new FullyQualifiedJavaType(String.class.getName())));
127
128 typeMap.put(Types.TIME_WITH_TIMEZONE, new JdbcTypeInformation("TIME_WITH_TIMEZONE",
129 new FullyQualifiedJavaType(OffsetTime.class.getName())));
130 typeMap.put(Types.TIMESTAMP_WITH_TIMEZONE, new JdbcTypeInformation("TIMESTAMP_WITH_TIMEZONE",
131 new FullyQualifiedJavaType(OffsetDateTime.class.getName())));
132 }
133
134 @Override
135 public void addConfigurationProperties(Properties properties) {
136 this.properties.putAll(properties);
137 forceBigDecimals = isTrue(properties.getProperty(PropertyRegistry.TYPE_RESOLVER_FORCE_BIG_DECIMALS));
138 }
139
140 @Override
141 public Optional<JdbcTypeInformation> calculateTypeInformation(IntrospectedColumn introspectedColumn) {
142 JdbcTypeInformation jdbcTypeInformation = typeMap.get(introspectedColumn.getJdbcType());
143 if (jdbcTypeInformation != null) {
144 return Optional.of(overrideDefault(introspectedColumn, jdbcTypeInformation));
145 } else {
146 return Optional.empty();
147 }
148 }
149
150 protected JdbcTypeInformation overrideDefault(IntrospectedColumn column,
151 JdbcTypeInformation defaultTypeInformation) {
152 return switch (column.getJdbcType()) {
153 case Types.BIT -> overrideBitType(column, defaultTypeInformation);
154 case Types.DECIMAL, Types.NUMERIC -> overrideBigDecimalType(column, defaultTypeInformation);
155 default -> defaultTypeInformation;
156 };
157 }
158
159 protected JdbcTypeInformation overrideBitType(IntrospectedColumn column,
160 JdbcTypeInformation defaultTypeInformation) {
161 if (column.getLength() > 1) {
162 return defaultTypeInformation.withJavaType(new FullyQualifiedJavaType("byte[]"));
163 } else {
164 return defaultTypeInformation;
165 }
166 }
167
168 protected JdbcTypeInformation overrideBigDecimalType(IntrospectedColumn column,
169 JdbcTypeInformation defaultTypeInformation) {
170 if (column.getScale() > 0 || column.getLength() > 18 || forceBigDecimals) {
171 return defaultTypeInformation;
172 } else if (column.getLength() > 9) {
173 return defaultTypeInformation.withJavaType(new FullyQualifiedJavaType(Long.class.getName()));
174 } else if (column.getLength() > 4) {
175 return defaultTypeInformation.withJavaType(new FullyQualifiedJavaType(Integer.class.getName()));
176 } else {
177 return defaultTypeInformation.withJavaType(new FullyQualifiedJavaType(Short.class.getName()));
178 }
179 }
180
181 @Override
182 public void setWarnings(List<String> warnings) {
183 this.warnings = warnings;
184 }
185
186 @Override
187 public void setContext(Context context) {
188 this.context = context;
189 }
190 }