GORM: mapping large text fields database agnostica

2019-02-15 12:16发布

问题:

I have a Grails application that will run against either a SQL Server or Oracle backend. I am using GORM as an ORM.

I want to map a large text field in a way that supports both database types. In my Grails domain class I have something like:

class Note {
    String content

    static constraints = {
        content nullable: false, blank: false
    }
}

I then declare database tables that look like this:

-- oracle
CREATE TABLE NOTE 
(
    id NUMBER(19, 0) NOT NULL,
    version NUMBER(19, 0) NOT NULL,
    content CLOB NOT NULL
);

-- SQL Server
CREATE TABLE NOTE 
(
    id NUMERIC(19, 0) NOT NULL,
    version NUMERIC(19, 0) NOT NULL,
    content NVARCHAR(MAX) NOT NULL
);

GORM is running in validate mode on startup, and I can't find a combination of Oracle and SQL Server data types and GORM mappings that allow the storage or large text fields without GORM failing to start correctly.

I have tried:

  • setting the type to text in mappings, but this doesn't seem to work. Oracle complains about expecting the content field to be of type long, and SQL Server wants a type of text in these circumstances.

  • setting the type to clob, which passes schema validation but then doesn't allow me to set the field as a string value - GORM expects data of type CLOB.

How should I configure my database definitions and GORM to make this work?

回答1:

As hackish as it is, a solution eventually emerged: by querying the Grails configuration at startup time, you can select an appropriate data type.

class Note {

    String content

    static constraints = {
        content nullable: false, blank: false
    }

    static mappings = {
        content sqlType: DbSupport.bigStringType
    }
}

class DbSupport {

    static def getBigStringType() {

        // examine which hibernate dialect is selected, and pick
        // an appropriate type mapping for that database type:
        def dialect = ApplicationHolder.application.config.dataSource.dialect
        switch (dialect) {

            case "org.hibernate.dialect.SQLServerDialect":
                return "nvarchar"
                break

            case "org.hibernate.dialect.Oracle10gDialect":
                return "clob"
                break
        }

    }
}