{"id":67,"date":"2012-04-21T16:31:04","date_gmt":"2012-04-21T16:31:04","guid":{"rendered":"https:\/\/zorq.net\/b\/?p=67"},"modified":"2012-09-12T11:40:18","modified_gmt":"2012-09-12T11:40:18","slug":"switching-hibernates-uuid-type-mapping-per-database","status":"publish","type":"post","link":"https:\/\/zorq.net\/b\/2012\/04\/21\/switching-hibernates-uuid-type-mapping-per-database\/","title":{"rendered":"Switching Hibernate&#8217;s UUID Type Mapping per Database"},"content":{"rendered":"<p>JDBC doesn&#8217;t include UUIDs as one of its <a title=\"JDBC SQL Types\" href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/java\/sql\/Types.html\">generic SQL types<\/a> and so the different relational databases supported by Hibernate have different mechanisms to save and retrieve UUIDs. PostgreSQL&#8217;s JDBC driver, for example, requires that you use <code>Types.OTHER<\/code> as a surrogate for the missing UUID constant:<\/p>\n<pre lang=\"java\">preparedStatement.setObject( index, uuid, Types.OTHER );<\/pre>\n<p>Whereas H2 requires the simpler:<\/p>\n<pre lang=\"java\">preparedStatement.setObject( index, uuid );<\/pre>\n<p>Developers may also choose not to use a database&#8217;s native mechanism, preferring instead to stipulate storage using a 36 character string or as an ordinary binary number. The way of telling Hibernate which mechanism you wish to use is done using an <code>@Type<\/code> annotation on the column:<\/p>\n<pre lang=\"java\">@Type(\"pg-uuid\")\r\nprivate UUID id;<\/pre>\n<p>Or an <code>@TypeDef<\/code> annotation on the package object:<\/p>\n<pre lang=\"java\">@TypeDef(\r\n        name = \"pg-uuid\",\r\n        defaultForType = UUID.class,\r\n        typeClass = PostgresUUIDType.class\r\n)\r\npackage com.example.domain;<\/pre>\n<p>This works fine with one database, but causes problems when you wish to test your application with a different database. The solution is to create another Hibernate type definition which can delegate to a database specific type depending on some environmental setting.<\/p>\n<p>The following implementation loads the database dialect in use from a properties file on the classpath. Strictly speaking, this information is already available in the <code>persistence.xml<\/code> file, but extracting that would entail much more effort. This is done just once when the class is loaded, so shouldn&#8217;t result in a performance impact.<\/p>\n<pre lang=\"java\">\/**\r\n * @author David Beaumont\r\n * @see org.hibernate.type.PostgresUUIDType\r\n *\/\r\npublic class UUIDCustomType extends AbstractSingleColumnStandardBasicType {\r\n\r\n    private static final long serialVersionUID = 902830399800029445L;\r\n\r\n    private static final SqlTypeDescriptor SQL_DESCRIPTOR;\r\n    private static final JavaTypeDescriptor TYPE_DESCRIPTOR;\r\n\r\n    static {\r\n        Properties properties = new Properties();\r\n        try {\r\n            ClassLoader loader = Thread.currentThread().getContextClassLoader();\r\n            properties.load(loader.getResourceAsStream(\"database.properties\"));\r\n        } catch (IOException e) {\r\n            throw new RuntimeException(\"Could not load properties!\", e);\r\n        }\r\n\r\n        String dialect = properties.getProperty(\"dialect\");\r\n        if(dialect.equals(\"org.hibernate.dialect.PostgreSQLDialect\")) {\r\n            SQL_DESCRIPTOR = PostgresUUIDType.PostgresUUIDSqlTypeDescriptor.INSTANCE;\r\n        } else if(dialect.equals(\"org.hibernate.dialect.H2Dialect\")) {\r\n            SQL_DESCRIPTOR = VarcharTypeDescriptor.INSTANCE;\r\n        } else {\r\n            throw new UnsupportedOperationException(\"Unsupported database!\");\r\n        }\r\n\r\n        TYPE_DESCRIPTOR = UUIDTypeDescriptor.INSTANCE;\r\n    }\r\n\r\n    public UUIDCustomType() {\r\n        super(SQL_DESCRIPTOR, TYPE_DESCRIPTOR);\r\n    }\r\n\r\n    @Override\r\n    public String getName() {\r\n        return \"uuid-custom\";\r\n    }\r\n\r\n}<\/pre>\n<p>Now you just have to register this new type as detailed above using <code>@Type(\"uuid-custom\")<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JDBC doesn&#8217;t include UUIDs as one of its generic SQL types and so the different relational databases supported by Hibernate have different mechanisms to save and retrieve UUIDs. PostgreSQL&#8217;s JDBC driver, for example, requires that you use Types.OTHER as a surrogate for the missing UUID constant: preparedStatement.setObject( index, uuid, Types.OTHER ); Whereas H2 requires the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[11,22,14,13,12],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-java","tag-hibernate","tag-java","tag-postgres","tag-testing","tag-uuid"],"_links":{"self":[{"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":28,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":97,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/posts\/67\/revisions\/97"}],"wp:attachment":[{"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zorq.net\/b\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}