View Javadoc
1   /*
2    *    Copyright 2006-2026 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.generator.api;
17  
18  import java.sql.Types;
19  import java.util.Objects;
20  import java.util.Optional;
21  import java.util.Properties;
22  
23  import org.jspecify.annotations.Nullable;
24  import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
25  import org.mybatis.generator.config.Context;
26  import org.mybatis.generator.internal.util.StringUtility;
27  
28  /**
29   * This class holds information about an introspected column.
30   *
31   * @author Jeff Butler
32   */
33  public class IntrospectedColumn {
34      /**
35       * Only nullable because instances of this class are built through introspection. Not null in practice.
36       */
37      protected @Nullable String actualColumnName;
38  
39      protected int jdbcType;
40  
41      /**
42       * The platform specific data type name as reported from DatabaseMetadata.getColumns().
43       *
44       * <p>Only nullable because instances of this class are built through introspection. Not null in practice.
45       */
46      protected @Nullable String actualTypeName;
47  
48      protected @Nullable String jdbcTypeName;
49  
50      protected boolean nullable;
51  
52      protected int length;
53  
54      protected int scale;
55  
56      protected boolean identity;
57  
58      protected boolean isSequenceColumn;
59  
60      /**
61       * Only nullable because instances of this class are built through introspection. Not null in practice.
62       */
63      protected @Nullable String javaProperty;
64  
65      /**
66       * Only nullable because instances of this class are built through introspection. Not null in practice.
67       */
68      protected @Nullable FullyQualifiedJavaType fullyQualifiedJavaType;
69  
70      protected @Nullable String tableAlias;
71  
72      protected @Nullable String typeHandler;
73  
74      /**
75       * Only nullable because instances of this class are built through introspection. Not null in practice.
76       */
77      protected @Nullable Context context;
78  
79      protected boolean isColumnNameDelimited;
80  
81      /**
82       * Only nullable because instances of this class are built through introspection. Not null in practice.
83       */
84      protected @Nullable IntrospectedTable introspectedTable;
85  
86      protected final Properties properties;
87  
88      // any database comment associated with this column. May be null
89      protected @Nullable String remarks;
90  
91      protected @Nullable String defaultValue;
92  
93      /**
94       * true if the JDBC driver reports that this column is auto-increment.
95       */
96      protected boolean isAutoIncrement;
97  
98      /**
99       * true if the JDBC driver reports that this column is generated.
100      */
101     protected boolean isGeneratedColumn;
102 
103     /**
104      * True if there is a column override that defines this column as GENERATED ALWAYS.
105      */
106     protected boolean isGeneratedAlways;
107 
108     /**
109      * Constructs a Column definition. This object holds all the information
110      * about a column that is required to generate Java objects and SQL maps;
111      */
112     public IntrospectedColumn() {
113         properties = new Properties();
114     }
115 
116     public int getJdbcType() {
117         return jdbcType;
118     }
119 
120     public void setJdbcType(int jdbcType) {
121         this.jdbcType = jdbcType;
122     }
123 
124     public int getLength() {
125         return length;
126     }
127 
128     public void setLength(int length) {
129         this.length = length;
130     }
131 
132     public boolean isNullable() {
133         return nullable;
134     }
135 
136     public void setNullable(boolean nullable) {
137         this.nullable = nullable;
138     }
139 
140     public int getScale() {
141         return scale;
142     }
143 
144     public void setScale(int scale) {
145         this.scale = scale;
146     }
147 
148     /*
149      * This method is primarily used for debugging, so we don't externalize the
150      * strings
151      */
152     @Override
153     public String toString() {
154         return "Actual Column Name: " //$NON-NLS-1$
155                 + getActualColumnName()
156                 + ", JDBC Type: " //$NON-NLS-1$
157                 + jdbcType
158                 + ", Nullable: " //$NON-NLS-1$
159                 + nullable
160                 + ", Length: " //$NON-NLS-1$
161                 + length
162                 + ", Scale: " //$NON-NLS-1$
163                 + scale
164                 + ", Identity: " //$NON-NLS-1$
165                 + identity;
166     }
167 
168     public void setActualColumnName(String actualColumnName) {
169         this.actualColumnName = actualColumnName;
170         isColumnNameDelimited = StringUtility.stringContainsSpace(actualColumnName);
171     }
172 
173     public boolean isIdentity() {
174         return identity;
175     }
176 
177     public void setIdentity(boolean identity) {
178         this.identity = identity;
179     }
180 
181     public boolean isBLOBColumn() {
182         String typeName = getJdbcTypeName();
183 
184         return "BINARY".equals(typeName) || "BLOB".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$
185                 || "CLOB".equals(typeName) || "LONGNVARCHAR".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$
186                 || "LONGVARBINARY".equals(typeName) || "LONGVARCHAR".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$
187                 || "NCLOB".equals(typeName) || "VARBINARY".equals(typeName); //$NON-NLS-1$ //$NON-NLS-2$
188     }
189 
190     public boolean isStringColumn() {
191         return getFullyQualifiedJavaType().equals(FullyQualifiedJavaType.getStringInstance());
192     }
193 
194     public boolean isJdbcCharacterColumn() {
195         return jdbcType == Types.CHAR || jdbcType == Types.CLOB
196                 || jdbcType == Types.LONGVARCHAR || jdbcType == Types.VARCHAR
197                 || jdbcType == Types.LONGNVARCHAR || jdbcType == Types.NCHAR
198                 || jdbcType == Types.NCLOB || jdbcType == Types.NVARCHAR;
199     }
200 
201     public String getJavaProperty() {
202         return getJavaProperty(null);
203     }
204 
205     public String getJavaProperty(@Nullable String prefix) {
206         String baseProperty = Objects.requireNonNull(javaProperty);
207         if (prefix == null) {
208             return baseProperty;
209         }
210 
211         return prefix + baseProperty;
212     }
213 
214     public void setJavaProperty(String javaProperty) {
215         this.javaProperty = javaProperty;
216     }
217 
218     public boolean isJDBCDateColumn() {
219         return getFullyQualifiedJavaType().equals(FullyQualifiedJavaType.getDateInstance())
220                 && "DATE".equalsIgnoreCase(jdbcTypeName); //$NON-NLS-1$
221     }
222 
223     public boolean isJDBCTimeColumn() {
224         return getFullyQualifiedJavaType().equals(FullyQualifiedJavaType.getDateInstance())
225                 && "TIME".equalsIgnoreCase(jdbcTypeName); //$NON-NLS-1$
226     }
227 
228     public Optional<String> getTypeHandler() {
229         return Optional.ofNullable(typeHandler);
230     }
231 
232     public void setTypeHandler(String typeHandler) {
233         this.typeHandler = typeHandler;
234     }
235 
236     public String getActualColumnName() {
237         return Objects.requireNonNull(actualColumnName);
238     }
239 
240     public void setColumnNameDelimited(boolean isColumnNameDelimited) {
241         this.isColumnNameDelimited = isColumnNameDelimited;
242     }
243 
244     public boolean isColumnNameDelimited() {
245         return isColumnNameDelimited;
246     }
247 
248     public String getJdbcTypeName() {
249         return StringUtility.stringValueOrElse(jdbcTypeName, "OTHER");//$NON-NLS-1$
250     }
251 
252     public void setJdbcTypeName(@Nullable String jdbcTypeName) {
253         this.jdbcTypeName = jdbcTypeName;
254     }
255 
256     public FullyQualifiedJavaType getFullyQualifiedJavaType() {
257         return Objects.requireNonNull(fullyQualifiedJavaType);
258     }
259 
260     public void setFullyQualifiedJavaType(FullyQualifiedJavaType fullyQualifiedJavaType) {
261         this.fullyQualifiedJavaType = fullyQualifiedJavaType;
262     }
263 
264     public Optional<String> getTableAlias() {
265         return Optional.ofNullable(tableAlias);
266     }
267 
268     public void setTableAlias(@Nullable String tableAlias) {
269         this.tableAlias = tableAlias;
270     }
271 
272     public Context getContext() {
273         return Objects.requireNonNull(context);
274     }
275 
276     public void setContext(Context context) {
277         this.context = context;
278     }
279 
280     public IntrospectedTable getIntrospectedTable() {
281         return Objects.requireNonNull(introspectedTable);
282     }
283 
284     public void setIntrospectedTable(IntrospectedTable introspectedTable) {
285         this.introspectedTable = introspectedTable;
286     }
287 
288     public Properties getProperties() {
289         return properties;
290     }
291 
292     public void setProperties(Properties properties) {
293         this.properties.putAll(properties);
294     }
295 
296     public Optional<String> getRemarks() {
297         return Optional.ofNullable(remarks);
298     }
299 
300     public void setRemarks(String remarks) {
301         this.remarks = remarks;
302     }
303 
304     public Optional<String> getDefaultValue() {
305         return Optional.ofNullable(defaultValue);
306     }
307 
308     public void setDefaultValue(@Nullable String defaultValue) {
309         this.defaultValue = defaultValue;
310     }
311 
312     public boolean isSequenceColumn() {
313         return isSequenceColumn;
314     }
315 
316     public void setSequenceColumn(boolean isSequenceColumn) {
317         this.isSequenceColumn = isSequenceColumn;
318     }
319 
320     public boolean isAutoIncrement() {
321         return isAutoIncrement;
322     }
323 
324     public void setAutoIncrement(boolean isAutoIncrement) {
325         this.isAutoIncrement = isAutoIncrement;
326     }
327 
328     public boolean isGeneratedColumn() {
329         return isGeneratedColumn;
330     }
331 
332     public void setGeneratedColumn(boolean isGeneratedColumn) {
333         this.isGeneratedColumn = isGeneratedColumn;
334     }
335 
336     public boolean isGeneratedAlways() {
337         return isGeneratedAlways;
338     }
339 
340     public void setGeneratedAlways(boolean isGeneratedAlways) {
341         this.isGeneratedAlways = isGeneratedAlways;
342     }
343 
344     /**
345      * The platform specific type name as reported by the JDBC driver. This value is determined
346      * from the DatabaseMetadata.getColumns() call - specifically ResultSet.getString("TYPE_NAME").
347      * This value is platform dependent.
348      *
349      * @return the platform specific type name as reported by the JDBC driver
350      */
351     public String getActualTypeName() {
352         return Objects.requireNonNull(actualTypeName);
353     }
354 
355     public void setActualTypeName(String actualTypeName) {
356         this.actualTypeName = actualTypeName;
357     }
358 }