Skip to content

Commit 8223ff2

Browse files
committed
Introduce overriding the default type map. fixes #16
1 parent 98cda9c commit 8223ff2

File tree

16 files changed

+479
-43
lines changed

16 files changed

+479
-43
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# EasyDao Changelog:
22

3+
## 3.2.0
4+
5+
* Overriding of the default type map is now possible through a replacement-type.properties #16
6+
* Small localization fixes
7+
38
## 3.1.0
49

510
* Handling Oracle virtual (read-only) fields #13

README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ Configuration example:
190190
<replacementTableFilename>replacement-table</replacementTableFilename>
191191
<replacementFieldFilename>replacement-field</replacementFieldFilename>
192192
<enumFieldFilename>enum-field</enumFieldFilename>
193+
<replacementTypeFilename>replacement-type</replacementTypeFilename>
193194
<sequenceNameConvention>PREFIXED_TABLE_NAME</sequenceNameConvention>
194195
<generateModelToString>false</generateModelToString>
195196
<licenseFilename>${baesdir}/src/myLicense.txt</licenseFilename>
@@ -296,6 +297,16 @@ If you want to use Java enum for a database field, put it into the file as TABLE
296297
CUS_CUSTOMER_ORDER.ORDER_MODE = hu.vanio.myapp.model.OrderMode
297298
```
298299

300+
## replacementTypeFilename
301+
302+
Map file name for databse types that should not be mapped by the default type map. Resource bundle file in src/main/resources without file extension, e.g: replacement-type
303+
304+
If you want to use a custom type instead of the built in one for one or a set of database types, put it into the file as <type name regex pattern> = <fully qualified classname of the type>, <fully qualified classname of the type converter>, e.g:
305+
306+
```
307+
date.* = hu.vanio.myapp.model.MyCustomDateType, hu.vanio.myapp.converter.MyCustomDateTypeConverter
308+
```
309+
299310
## sequenceNameConvention
300311
Defines database sequence naming convention with **SEQ** string, optional, default value is SUFFIXED_TABLE_NAME.
301312

@@ -417,6 +428,85 @@ public enum MyFieldIrregularEnum {
417428
}
418429
```
419430

431+
# Using custom types
432+
433+
EasyDAO maps database types to the most sensible Java types, but sometimes it's not appropriate. In these cases you can
434+
override the default type mapping via a properties file. Overriding it consists of the following:
435+
436+
* implementation of the custom type class, see the example below.
437+
* implementation of a type converter class that converts the custom type to a type that is recognized by the database driver and/or spring JDBC, see the example below
438+
* registering the custom type in the replacement-type.properties and specifying the file name in the maven plugin configuration
439+
440+
441+
Let's assume we have an Oracle database and the default DATE -> java.sql.Timestamp mapping is not appropriate for some reason.
442+
In this case we need to implement the MyCustomDateType class and the corresponding MyCustomDateTypeConverter as seen below.
443+
In addition you have to register the new custom type in the replacement type map file (replacement-type.properties):
444+
```
445+
date.* = hu.vanio.myapp.model.MyCustomDateType, hu.vanio.myapp.converter.MyCustomDateTypeConverter
446+
```
447+
> Note the `date.*` expression on the left hand side. It means that *any* field with a type that starts with the string `date` will be mapped to the given custom type.
448+
449+
### Example custom type class
450+
451+
452+
```java
453+
package hu.vanio.myapp.model;
454+
455+
public class MyCustomDateType {
456+
457+
// properties...
458+
459+
// methods...
460+
461+
/** Constructor */
462+
public MyCustomDateType(String) {
463+
// ...
464+
}
465+
466+
public java.sql.Date toSqlDate() {
467+
java.sql.Date dateValue = ....
468+
return dateValue;
469+
}
470+
471+
}
472+
```
473+
474+
### Example type converter implementation
475+
476+
Type converters are convention based so it's not necessary to extend any base class or implement any interface.
477+
The only requirement is to implement two public static methods: extractValue and convertValue.
478+
479+
> WARNING: This class must be thread safe, so don't use any instance fields!
480+
481+
```java
482+
package hu.vanio.myapp.converter;
483+
484+
import hu.vanio.myapp.model.MyCustomDateType;
485+
486+
/** Converter class. */
487+
public class MyCustomDateTypeConverter {
488+
489+
/**
490+
* Extracts the value of the field with the specified name as a custom type from the specified resultset.
491+
* is of type DATE you have to return either java.util.Date, java.sql.Date or java.sql.Timestamp.
492+
*/
493+
static public MyCustomDateType extractValue(ResultSet rs, String fieldName) throws SQLException {
494+
String strValue = rs.getString(fieldName);
495+
return new MyCustomDateType(strValue);
496+
}
497+
498+
/**
499+
* Maps the custom Java type to a Java type that can be written to the database field. i.e. if the database field
500+
* is of type DATE you have to return either java.util.Date, java.sql.Date or java.sql.Timestamp.
501+
*/
502+
static public Date convertValue(MyCustomDateType value) {
503+
// Additional processing may come here
504+
return value.toSqlDate();
505+
}
506+
507+
}
508+
```
509+
420510
> If you just want **to use** this easy model and dao generator, then use the maven plugin at https://github.com/vanioinformatika/easydao-maven-plugin and a small dependeny in your project: https://github.com/vanioinformatika/easydao-core
421511
422512

easydao-maven-plugin/src/main/java/hu/vanio/easydao/EngineConfiguration.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,18 @@ static public enum SEQUENCE_NAME_CONVENTION {
128128
* You can disable Java source generation for a certain field by putting the field name in the list with no Java field name.
129129
* e.g.: USER.FNAME = */
130130
private final String replacementFieldFilename;
131-
131+
132132
/** Map of Java enum names and database field names. Names included in this list will be generated with the specified enum type.
133133
* The key is the table name and field name, the value is the fully qualified name of the enum.
134134
* e.g.: USER.STATE = hu.vanio.myapp.model.UserState */
135135
private final String enumFieldFilename;
136136

137+
/** Filename for the replacement map of database types and Java types. Types not included in this map will be generated
138+
* according to the default type map.
139+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
140+
*/
141+
private final String replacementTypeMapFilename;
142+
137143
/** License file name (its content will be inserted into all generated Java source files) */
138144
private final String licenseFilename;
139145
/** License text */
@@ -149,6 +155,12 @@ static public enum SEQUENCE_NAME_CONVENTION {
149155
* e.g.: USER.STATE = hu.vanio.myapp.model.UserState */
150156
private Map<String, String> enumFieldMap = new HashMap<>();
151157

158+
/** Replacement map of database types and Java types. Types not included in this map will be generated according
159+
* to the default type map.
160+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
161+
*/
162+
private Map<String, String> replacementTypeMap = new HashMap<>();
163+
152164
/**
153165
* Engine configuration init.
154166
* @param databaseName database name: generated Dao DataSource name in @Qualifier annotation
@@ -177,6 +189,9 @@ static public enum SEQUENCE_NAME_CONVENTION {
177189
* @param enumFieldFilename Map of Java enum names and database field names. Names included in this list will be generated with the specified enum type.
178190
* The key is the table name and field name, the value is the fully qualified name of the enum.
179191
* e.g.: USER.STATE = hu.vanio.myapp.model.UserState
192+
* @param replacementTypeMapFilename Filename for the replacement map of database types and Java types. Types not included in
193+
* this list will be generated according to the default type map.
194+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
180195
* @param licenseFilename License file name (its content will be inserted into all generated Java source files)
181196
* @param tableNameIncludes
182197
* @param encoding Encoding of the generated source files
@@ -190,7 +205,7 @@ public EngineConfiguration(
190205
String packageOfJavaDao, String daoSuffix,
191206
boolean generateModelToString,
192207
SEQUENCE_NAME_CONVENTION sequenceNameConvention,
193-
String replacementTableFilename, String replacementFieldFilename, String enumFieldFilename,
208+
String replacementTableFilename, String replacementFieldFilename, String enumFieldFilename, String replacementTypeMapFilename,
194209
String licenseFilename,
195210
List<String> tableNameIncludes,
196211
String encoding,
@@ -214,6 +229,7 @@ public EngineConfiguration(
214229
this.replacementTableFilename = replacementTableFilename;
215230
this.replacementFieldFilename = replacementFieldFilename;
216231
this.enumFieldFilename = enumFieldFilename;
232+
this.replacementTypeMapFilename = replacementTypeMapFilename;
217233
this.licenseFilename = licenseFilename;
218234
this.tableNameIncludes = tableNameIncludes;
219235
this.encoding = encoding;
@@ -231,6 +247,9 @@ public EngineConfiguration(
231247
if (this.enumFieldFilename != null) {
232248
loadResourceBundleToMap(this.enumFieldFilename, this.enumFieldMap);
233249
}
250+
if (this.replacementTypeMapFilename != null) {
251+
loadResourceBundleToMap(this.replacementTypeMapFilename, this.replacementTypeMap);
252+
}
234253

235254
if (this.licenseFilename != null) {
236255
this.licenseText = readFile(this.licenseFilename, Charset.forName(this.encoding));
@@ -278,6 +297,7 @@ static public EngineConfiguration createFromProperties(Properties props) throws
278297
props.getProperty("replacementTableFilename"),
279298
props.getProperty("replacementFieldFilename"),
280299
props.getProperty("enumFieldFilename"),
300+
props.getProperty("replacementTypeMapFilename"),
281301
props.getProperty("licenseFilename"),
282302
getPropertyAsList(props, "tableNameIncludes"),
283303
props.getProperty("encoding"),
@@ -534,6 +554,16 @@ public String getEnumFieldFilename() {
534554
return enumFieldFilename;
535555
}
536556

557+
/**
558+
* Filename for the replacement map of database types and Java types. Types not included in this map will be generated
559+
* according to the default type map.
560+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
561+
* @return the replacementTypeMapFilename
562+
*/
563+
public String getReplacementTypeMapFilename() {
564+
return replacementTypeMapFilename;
565+
}
566+
537567
/**
538568
* License file name (its content will be inserted into all generated Java source files)
539569
* @return the licenseFilename
@@ -600,6 +630,26 @@ public void setEnumFieldMap(Map<String, String> enumFieldMap) {
600630
this.enumFieldMap = enumFieldMap;
601631
}
602632

633+
/**
634+
* Replacement map of database types and Java types. Types not included in this map will be generated according
635+
* to the default type map.
636+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
637+
* @return the typeMap
638+
*/
639+
public Map<String, String> getReplacementTypeMap() {
640+
return replacementTypeMap;
641+
}
642+
643+
/**
644+
* Replacement map of database types and Java types. Types not included in this map will be generated according
645+
* to the default type map.
646+
* e.g.: date = java.util.Date -> java.util.Date instead of java.sql.Timestamp
647+
* @param typeMap the typeMap to set
648+
*/
649+
public void setTypeMap(Map<String, String> replacementTypeMap) {
650+
this.replacementTypeMap = replacementTypeMap;
651+
}
652+
603653
/**
604654
* The locale for generating comments
605655
* @return the locale
@@ -644,10 +694,14 @@ public String toString() {
644694
+ ", generateModelToString=" + generateModelToString
645695
+ ", replacementTableFilename=" + replacementTableFilename
646696
+ ", replacementFieldFilename=" + replacementFieldFilename
697+
+ ", enumFieldFilename=" + enumFieldFilename
698+
+ ", replacementTypeMapFilename=" + replacementTypeMapFilename
647699
+ ", licenseFilename=" + licenseFilename
648700
+ ", licenseText=" + licenseText
649701
+ ", replacementTableMap=" + replacementTableMap
650702
+ ", replacementFieldMap=" + replacementFieldMap
703+
+ ", enumFieldMap=" + enumFieldMap
704+
+ ", replacementTypeMap=" + replacementTypeMap
651705
+ ", locale=" + locale
652706
+ ", tableNameIncludes=" + tableNameIncludes
653707
+ ", encoding=" + encoding

easydao-maven-plugin/src/main/java/hu/vanio/easydao/model/Field.java

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public class Field {
5151
private String javaName;
5252
/** The type of this field in Java code */
5353
private String javaType;
54+
55+
/** Indicates whether this field has a custom type */
56+
private boolean customType;
57+
/** The type converter for this field (optional) */
58+
private String typeConverterClass;
5459

5560
/**
5661
* Constructor
@@ -73,6 +78,8 @@ public Field(boolean primaryKey,
7378
boolean array,
7479
boolean enumerated,
7580
boolean irregularEnum,
81+
boolean customType,
82+
String typeConverterClass,
7683
String dbName,
7784
String dbType,
7885
String comment,
@@ -84,6 +91,8 @@ public Field(boolean primaryKey,
8491
this.array = array;
8592
this.enumerated = enumerated;
8693
this.irregularEnum = irregularEnum;
94+
this.customType = customType;
95+
this.typeConverterClass = typeConverterClass;
8796
this.dbName = dbName;
8897
this.dbType = dbType;
8998
this.comment = comment;
@@ -93,9 +102,21 @@ public Field(boolean primaryKey,
93102

94103
@Override
95104
public String toString() {
96-
return "Field{" + "dbName: \"" + dbName + "\", javaName: \"" + javaName + "\", dbType: \"" + dbType + "\", javaType: \"" + getJavaType()
97-
+ "\", primaryKey: " + primaryKey + ", nullable: " + nullable + ", array: " + array + ", enumerated: " + enumerated
98-
+ ", comment: \"" + comment + "\"}";
105+
return "Field{" +
106+
"dbName: " + dbName +
107+
", javaName: " + javaName +
108+
", dbType: " + dbType +
109+
", javaType: " + getJavaType() +
110+
", primaryKey: " + primaryKey +
111+
", nullable: " + nullable +
112+
", array: " + array +
113+
", enumerated: " + enumerated +
114+
", irregularEnum: " + irregularEnum +
115+
", virtual: " + virtual +
116+
", customType: " + customType +
117+
", typeConverterClass: " + typeConverterClass +
118+
", comment: " + comment +
119+
"\"}";
99120
}
100121

101122
/**
@@ -291,6 +312,38 @@ public void setJavaType(String javaType) {
291312
this.javaType = javaType;
292313
}
293314

315+
/**
316+
* Indicates whether this field has a custom type
317+
* @return the customType
318+
*/
319+
public boolean isCustomType() {
320+
return customType;
321+
}
322+
323+
/**
324+
* Indicates whether this field has a custom type
325+
* @param customType the customType to set
326+
*/
327+
public void setCustomType(boolean customType) {
328+
this.customType = customType;
329+
}
330+
331+
/**
332+
* The type converter for this field (optional)
333+
* @return the typeConverterClass
334+
*/
335+
public String getTypeConverterClass() {
336+
return typeConverterClass;
337+
}
338+
339+
/**
340+
* The type converter for this field (optional)
341+
* @param typeConverterClass the typeConverterClass to set
342+
*/
343+
public void setTypeConverterClass(String typeConverterClass) {
344+
this.typeConverterClass = typeConverterClass;
345+
}
346+
294347
/**
295348
* indicates whether the value of this field sould be read from the resultset as a String
296349
* @return true if this field should be read from the resultset as a String
@@ -311,7 +364,8 @@ public boolean isReadAsString() {
311364
&& javaClass != java.sql.Clob.class
312365
&& javaClass != java.sql.Blob.class
313366
&& !javaClass.isArray()
314-
&& !this.enumerated) {
367+
&& !this.enumerated
368+
&& !this.customType) {
315369
retVal = true;
316370
}
317371
return retVal;

0 commit comments

Comments
 (0)