diff --git a/src/main/java/com/avaje/ebean/config/CustomDbTypeMapping.java b/src/main/java/com/avaje/ebean/config/CustomDbTypeMapping.java
new file mode 100644
index 000000000..ae6a7d244
--- /dev/null
+++ b/src/main/java/com/avaje/ebean/config/CustomDbTypeMapping.java
@@ -0,0 +1,54 @@
+package com.avaje.ebean.config;
+
+import com.avaje.ebean.config.dbplatform.DbType;
+
+/**
+ * Custom mappings for DB types that override the default.
+ *
+ * @see ServerConfig#addCustomMapping(DbType, String)
+ */
+public class CustomDbTypeMapping {
+
+ protected final DbType type;
+
+ protected final String columnDefinition;
+
+ protected final Platform platform;
+
+ /**
+ * Create a mapping.
+ */
+ public CustomDbTypeMapping(DbType type, String columnDefinition, Platform platform) {
+ this.type = type;
+ this.columnDefinition = columnDefinition;
+ this.platform = platform;
+ }
+
+ /**
+ * Create a mapping that should apply to all the database platforms.
+ */
+ public CustomDbTypeMapping(DbType type, String columnDefinition) {
+ this(type, columnDefinition, null);
+ }
+
+ /**
+ * Return the DB type the mapping applies to.
+ */
+ public DbType getType() {
+ return type;
+ }
+
+ /**
+ * Return the DB column definition to use.
+ */
+ public String getColumnDefinition() {
+ return columnDefinition;
+ }
+
+ /**
+ * Return the platform this mapping should apply to. Null means it applied to all platforms.
+ */
+ public Platform getPlatform() {
+ return platform;
+ }
+}
diff --git a/src/main/java/com/avaje/ebean/config/DbMigrationConfig.java b/src/main/java/com/avaje/ebean/config/DbMigrationConfig.java
index ebb4d4889..5e4155289 100644
--- a/src/main/java/com/avaje/ebean/config/DbMigrationConfig.java
+++ b/src/main/java/com/avaje/ebean/config/DbMigrationConfig.java
@@ -1,7 +1,6 @@
package com.avaje.ebean.config;
import com.avaje.ebean.EbeanServer;
-import com.avaje.ebean.config.dbplatform.DbPlatformName;
import com.avaje.ebean.dbmigration.DbMigration;
import org.avaje.dbmigration.MigrationConfig;
import org.avaje.dbmigration.MigrationRunner;
@@ -20,7 +19,7 @@ public class DbMigrationConfig {
/**
* The database platform to generate migration DDL for.
*/
- protected DbPlatformName platform;
+ protected Platform platform;
/**
* Set to true if the DB migration should be generated on server start.
@@ -112,14 +111,14 @@ public class DbMigrationConfig {
* We typically need to explicitly specify this as migration can often be generated
* when running against H2.
*/
- public DbPlatformName getPlatform() {
+ public Platform getPlatform() {
return platform;
}
/**
* Set the DB platform to generate migration DDL for.
*/
- public void setPlatform(DbPlatformName platform) {
+ public void setPlatform(Platform platform) {
this.platform = platform;
}
@@ -366,7 +365,7 @@ public class DbMigrationConfig {
includeGeneratedFileComment = properties.getBoolean("migration.includeGeneratedFileComment", includeGeneratedFileComment);
generatePendingDrop = properties.get("migration.generatePendingDrop", generatePendingDrop);
- platform = properties.getEnum(DbPlatformName.class, "migration.platform", platform);
+ platform = properties.getEnum(Platform.class, "migration.platform", platform);
generate = properties.getBoolean("migration.generate", generate);
version = properties.get("migration.version", version);
diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformName.java b/src/main/java/com/avaje/ebean/config/Platform.java
similarity index 84%
rename from src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformName.java
rename to src/main/java/com/avaje/ebean/config/Platform.java
index 357e89b21..bba8d43e2 100644
--- a/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformName.java
+++ b/src/main/java/com/avaje/ebean/config/Platform.java
@@ -1,9 +1,9 @@
-package com.avaje.ebean.config.dbplatform;
+package com.avaje.ebean.config;
/**
* Built in supported platforms.
*/
-public enum DbPlatformName {
+public enum Platform {
/**
* Generic base platform configured via properties or code.
diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java
index 9dd0d05bb..70cf6dbcf 100644
--- a/src/main/java/com/avaje/ebean/config/ServerConfig.java
+++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java
@@ -7,6 +7,7 @@ import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.cache.ServerCachePlugin;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbEncrypt;
+import com.avaje.ebean.config.dbplatform.DbType;
import com.avaje.ebean.event.BeanFindController;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistListener;
@@ -83,6 +84,8 @@ public class ServerConfig {
private ContainerConfig containerConfig;
+ private List
* You can also set this in ebean.proprerties:
*
* {@code
* # set via ebean.properties
* ebean.encryptKeyManager=com.avaje.tests.basic.encrypt.BasicEncyptKeyManager
@@ -1770,7 +1773,7 @@ public class ServerConfig {
* queries that normally hit L2 bean cache automatically will not do so after a write/persist
* on the transaction.
*
*
{@code
*
* // assume Customer has L2 bean caching enabled ...
@@ -1932,6 +1935,54 @@ public class ServerConfig {
this.resourceDirectory = resourceDirectory;
}
+ /**
+ * Add a custom type mapping.
+ *
+ *
{@code
+ *
+ * // set the default mapping for BigDecimal.class/decimal
+ * serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
+ *
+ * // set the default mapping for String.class/varchar but only for Postgres
+ * serverConfig.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES);
+ *
+ * }
+ *
+ * @param type The DB type this mapping should apply to
+ * @param columnDefinition The column definition that should be used
+ * @param platform Optionally specify the platform this mapping should apply to.
+ */
+ public void addCustomMapping(DbType type, String columnDefinition, Platform platform) {
+ customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition, platform));
+ }
+
+ /**
+ * Add a custom type mapping that applies to all platforms.
+ *
+ *
{@code
+ *
+ * // set the default mapping for BigDecimal/decimal
+ * serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
+ *
+ * // set the default mapping for String/varchar
+ * serverConfig.addCustomMapping(DbType.VARCHAR, "text");
+ *
+ * }
+ *
+ * @param type The DB type this mapping should apply to
+ * @param columnDefinition The column definition that should be used
+ */
+ public void addCustomMapping(DbType type, String columnDefinition) {
+ customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition));
+ }
+
+ /**
+ * Return the list of custom type mappings.
+ */
+ public List getCustomTypeMappings() {
+ return customDbTypeMappings;
+ }
+
/**
* Register a BeanQueryAdapter instance.
*
diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/DatabasePlatform.java b/src/main/java/com/avaje/ebean/config/dbplatform/DatabasePlatform.java
index 9416cc7ba..6289dd810 100644
--- a/src/main/java/com/avaje/ebean/config/dbplatform/DatabasePlatform.java
+++ b/src/main/java/com/avaje/ebean/config/dbplatform/DatabasePlatform.java
@@ -2,7 +2,9 @@ package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.Query;
+import com.avaje.ebean.config.CustomDbTypeMapping;
import com.avaje.ebean.config.PersistBatch;
+import com.avaje.ebean.config.Platform;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
@@ -180,6 +182,19 @@ public class DatabasePlatform {
*/
public void configure(ServerConfig serverConfig) {
dbTypeMap.config(nativeUuidType, serverConfig.getDbUuid());
+ for (CustomDbTypeMapping mapping : serverConfig.getCustomTypeMappings()) {
+ if (platformMatch(mapping.getPlatform())) {
+ dbTypeMap.put(mapping.getType(), parse(mapping.getColumnDefinition()));
+ }
+ }
+ }
+
+ private DbPlatformType parse(String columnDefinition) {
+ return DbPlatformType.parse(columnDefinition);
+ }
+
+ private boolean platformMatch(Platform platform) {
+ return platform == null || platform.name().equalsIgnoreCase(name);
}
/**
diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformType.java b/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformType.java
index 5ff8c2c6e..c2599d7aa 100644
--- a/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformType.java
+++ b/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformType.java
@@ -28,6 +28,17 @@ public class DbPlatformType implements ExtraDbTypes {
*/
private final boolean canHaveLength;
+ /**
+ * Parse a type definition into a DbPlatformType.
+ *
+ * e.g. "decimal(18,6)"
+ * e.g. "text"
+ *
+ */
+ public static DbPlatformType parse(String columnDefinition) {
+ return DbPlatformTypeParser.parse(columnDefinition);
+ }
+
/**
* Construct with no length or scale.
*/
@@ -67,6 +78,27 @@ public class DbPlatformType implements ExtraDbTypes {
this.canHaveLength = canHaveLength;
}
+ /**
+ * Return the type name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Return the default length/precision.
+ */
+ public int getDefaultLength() {
+ return defaultLength;
+ }
+
+ /**
+ * Return the default scale.
+ */
+ public int getDefaultScale() {
+ return defaultScale;
+ }
+
/**
* Return the type for a specific property that incorporates the name, length,
* precision and scale.
diff --git a/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParser.java b/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParser.java
new file mode 100644
index 000000000..14a1c60db
--- /dev/null
+++ b/src/main/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParser.java
@@ -0,0 +1,40 @@
+package com.avaje.ebean.config.dbplatform;
+
+/**
+ * Parse raw column definitions into DbPlatformType like "decimal(18,6)" and "varchar(20) and "json".
+ */
+class DbPlatformTypeParser {
+
+ /**
+ * Parse the column definition and return the DbPlatformType.
+ */
+ static DbPlatformType parse(String columnDefinition) {
+
+ columnDefinition = columnDefinition.trim();
+
+ int openPos = columnDefinition.indexOf('(');
+ if (openPos == -1) {
+ return new DbPlatformType(columnDefinition);
+ }
+ int closePos = columnDefinition.indexOf(')', openPos);
+ if (closePos == -1) {
+ return new DbPlatformType(columnDefinition);
+ }
+ try {
+ int commaPos = columnDefinition.indexOf(',', openPos);
+ if (commaPos > -1) {
+ String type = columnDefinition.substring(0, openPos);
+ int scale = Integer.parseInt(columnDefinition.substring(openPos + 1, commaPos));
+ int precision = Integer.parseInt(columnDefinition.substring(commaPos + 1, closePos));
+ return new DbPlatformType(type, scale, precision);
+
+ } else {
+ String type = columnDefinition.substring(0, openPos);
+ int scale = Integer.parseInt(columnDefinition.substring(openPos + 1, closePos));
+ return new DbPlatformType(type, scale);
+ }
+ } catch (RuntimeException e) {
+ return new DbPlatformType(columnDefinition);
+ }
+ }
+}
diff --git a/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java b/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java
index 18fff98cb..06692d82c 100644
--- a/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java
+++ b/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java
@@ -7,7 +7,7 @@ import com.avaje.ebean.config.DbMigrationConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DB2Platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
-import com.avaje.ebean.config.dbplatform.DbPlatformName;
+import com.avaje.ebean.config.Platform;
import com.avaje.ebean.config.dbplatform.H2Platform;
import com.avaje.ebean.config.dbplatform.MsSqlServer2005Platform;
import com.avaje.ebean.config.dbplatform.MySqlPlatform;
@@ -139,7 +139,7 @@ public class DbMigration {
* If not set this defaults to the platform of the default server.
*
*/
- public void setPlatform(DbPlatformName platform) {
+ public void setPlatform(Platform platform) {
setPlatform(getPlatform(platform));
}
@@ -163,7 +163,7 @@ public class DbMigration {
* from the migration (e.g. generate migration sql for MySql, Postgres and Oracle).
*
*/
- public void addPlatform(DbPlatformName platform, String prefix) {
+ public void addPlatform(Platform platform, String prefix) {
platforms.add(new Pair(getPlatform(platform), prefix));
}
@@ -515,7 +515,7 @@ public class DbMigration {
/**
* Return the DatabasePlatform given the platform key.
*/
- protected DatabasePlatform getPlatform(DbPlatformName platform) {
+ protected DatabasePlatform getPlatform(Platform platform) {
switch (platform) {
case H2:
return new H2Platform();
diff --git a/src/main/java/com/avaje/ebean/dbmigration/DbOffline.java b/src/main/java/com/avaje/ebean/dbmigration/DbOffline.java
index f0f8c3783..fb25efb57 100644
--- a/src/main/java/com/avaje/ebean/dbmigration/DbOffline.java
+++ b/src/main/java/com/avaje/ebean/dbmigration/DbOffline.java
@@ -1,6 +1,6 @@
package com.avaje.ebean.dbmigration;
-import com.avaje.ebean.config.dbplatform.DbPlatformName;
+import com.avaje.ebean.config.Platform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -19,7 +19,7 @@ public class DbOffline {
/**
* Set the platform to use when creating the next EbeanServer instance.
*/
- public static void setPlatform(DbPlatformName dbPlatform) {
+ public static void setPlatform(Platform dbPlatform) {
System.setProperty(KEY, dbPlatform.name());
}
@@ -41,7 +41,7 @@ public class DbOffline {
* Bring up the next EbeanServer instance using the H2 platform.
*/
public static void asH2() {
- setPlatform(DbPlatformName.H2);
+ setPlatform(Platform.H2);
}
/**
diff --git a/src/test/java/com/avaje/ebean/config/PropertiesWrapperTest.java b/src/test/java/com/avaje/ebean/config/PropertiesWrapperTest.java
index 43f8606c9..6337548ac 100644
--- a/src/test/java/com/avaje/ebean/config/PropertiesWrapperTest.java
+++ b/src/test/java/com/avaje/ebean/config/PropertiesWrapperTest.java
@@ -1,6 +1,5 @@
package com.avaje.ebean.config;
-import com.avaje.ebean.config.dbplatform.DbPlatformName;
import org.junit.Test;
import java.util.Properties;
@@ -25,9 +24,9 @@ public class PropertiesWrapperTest {
properties.put("platform","postgres");
PropertiesWrapper pw = new PropertiesWrapper("pref", "myserver", properties);
- assertEquals(DbPlatformName.POSTGRES, pw.getEnum(DbPlatformName.class, "platform", DbPlatformName.H2));
- assertEquals(DbPlatformName.H2, pw.getEnum(DbPlatformName.class, "junk", DbPlatformName.H2));
- assertNull(pw.getEnum(DbPlatformName.class, "junk", null));
+ assertEquals(Platform.POSTGRES, pw.getEnum(Platform.class, "platform", Platform.H2));
+ assertEquals(Platform.H2, pw.getEnum(Platform.class, "junk", Platform.H2));
+ assertNull(pw.getEnum(Platform.class, "junk", null));
}
@Test
diff --git a/src/test/java/com/avaje/ebean/config/dbplatform/DatabasePlatformTest.java b/src/test/java/com/avaje/ebean/config/dbplatform/DatabasePlatformTest.java
new file mode 100644
index 000000000..923834382
--- /dev/null
+++ b/src/test/java/com/avaje/ebean/config/dbplatform/DatabasePlatformTest.java
@@ -0,0 +1,46 @@
+package com.avaje.ebean.config.dbplatform;
+
+import com.avaje.ebean.config.Platform;
+import com.avaje.ebean.config.ServerConfig;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class DatabasePlatformTest {
+
+ @Test
+ public void defaultTypesForDecimalAndVarchar() throws Exception {
+
+ DatabasePlatform dbPlatform = new DatabasePlatform();
+ assertEquals(defaultDecimalDefn(dbPlatform), "decimal(38)");
+ assertEquals(defaultDefn(DbType.VARCHAR, dbPlatform), "varchar(255)");
+ }
+
+ @Test
+ public void configure_customType() throws Exception {
+
+ ServerConfig serverConfig = new ServerConfig();
+ serverConfig.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES);
+ serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(24,4)");
+
+ // PG renders custom decimal and varchar
+ PostgresPlatform pgPlatform = new PostgresPlatform();
+ pgPlatform.configure(serverConfig);
+ assertEquals(defaultDecimalDefn(pgPlatform), "decimal(24,4)");
+ assertEquals(defaultDefn(DbType.VARCHAR, pgPlatform), "text");
+
+ // H2 only renders custom decimal
+ H2Platform h2Platform = new H2Platform();
+ h2Platform.configure(serverConfig);
+ assertEquals(defaultDecimalDefn(h2Platform), "decimal(24,4)");
+ assertEquals(defaultDefn(DbType.VARCHAR, h2Platform), "varchar(255)");
+ }
+
+ private String defaultDecimalDefn(DatabasePlatform dbPlatform) {
+ return defaultDefn(DbType.DECIMAL, dbPlatform);
+ }
+
+ private String defaultDefn(DbType type, DatabasePlatform dbPlatform) {
+ return dbPlatform.getDbTypeMap().get(type).renderType(0, 0);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParserTest.java b/src/test/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParserTest.java
new file mode 100644
index 000000000..bc2990515
--- /dev/null
+++ b/src/test/java/com/avaje/ebean/config/dbplatform/DbPlatformTypeParserTest.java
@@ -0,0 +1,67 @@
+package com.avaje.ebean.config.dbplatform;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class DbPlatformTypeParserTest {
+
+ @Test
+ public void parse_text() throws Exception {
+
+ DbPlatformType type = DbPlatformTypeParser.parse("text");
+
+ assertEquals(type.getName(), "text");
+ assertEquals(type.getDefaultLength(), 0);
+ assertEquals(type.getDefaultScale(), 0);
+
+ assertEquals(type.renderType(0, 0), "text");
+ assertEquals(type.renderType(40, 0), "text(40)");
+ }
+
+ @Test
+ public void parse_varchar20() throws Exception {
+
+ DbPlatformType type = DbPlatformTypeParser.parse("varchar(20)");
+
+ assertEquals(type.getName(), "varchar");
+ assertEquals(type.getDefaultLength(), 20);
+ assertEquals(type.getDefaultScale(), 0);
+
+ assertEquals(type.renderType(0, 0), "varchar(20)");
+ assertEquals(type.renderType(40, 0), "varchar(40)");
+ }
+
+ @Test
+ public void parse_decimal_18_6() throws Exception {
+
+ DbPlatformType type = DbPlatformTypeParser.parse("decimal(18,6)");
+
+ assertEquals(type.getName(), "decimal");
+ assertEquals(type.getDefaultLength(), 18);
+ assertEquals(type.getDefaultScale(), 6);
+ assertEquals(type.renderType(0, 0), "decimal(18,6)");
+ }
+
+ @Test
+ public void parse_something() throws Exception {
+
+ DbPlatformType type = DbPlatformTypeParser.parse("something(asd,6)");
+
+ assertEquals(type.getName(), "something(asd,6)");
+ assertEquals(type.getDefaultLength(), 0);
+ assertEquals(type.getDefaultScale(), 0);
+ assertEquals(type.renderType(0, 0), "something(asd,6)");
+ }
+
+ @Test
+ public void parse_invalid() throws Exception {
+
+ DbPlatformType type = DbPlatformTypeParser.parse("something(asd");
+
+ assertEquals(type.getName(), "something(asd");
+ assertEquals(type.getDefaultLength(), 0);
+ assertEquals(type.getDefaultScale(), 0);
+ assertEquals(type.renderType(0, 0), "something(asd");
+ }
+}
\ No newline at end of file