【问题标题】:Saving a xml data type to MS SQL server using grails domain class使用 grails 域类将 xml 数据类型保存到 MS SQL 服务器
【发布时间】:2014-06-05 20:57:18
【问题描述】:

我正在尝试利用 MS SQL Server 的 xml 数据类型。 使用 grails 版本:2.3.4 我一直在使用 jdbc:h2 和 clob 数据类型。当我将数据库切换到 MS SQL Server 2012 时,一切正常,除非我尝试使用 sqlType: xml 和 UTF-8 编码进行保存。 UTF-16 编码工作正常......(但我需要 UTF-8 才能工作) 这是我的代码 领域类

class Message implements Serializable{

    long id 
    String message
    String messageType  

    static hasMany = [messageTracker: MessageTracker]

    static constraints = {      
        id nullable: false
        message (nullable: false, maxSize: 2147483646)
        messageType (inList: ["CDM", "MISMO"])      
    }

    static mapping = {
        table 'message'
        version false
        id column: 'message_id', generator: 'identity'
        message column: 'message', type:'text', sqlType: 'xml'
        messageType column: 'message_type'
    }
}

服务:

private Message insertMessage( String message, String messageType){
        log.info("Inside insertMessage Service")
            Message msg = new Message(message: message, messageType: messageType.toUpperCase())           
        if(!msg.save()){
                   log.error "Trouble saving message payload to Message table" + msg.errors
           throw new ValidationException(msg.errors)
        }

        return msg
    }

发生的奇怪事情是如果我尝试保存

<?xml version="1.0"  encoding="UTF-16"?>
<tag> this is a blah</tag>

一切正常。 (我不能使用编码 utf-16 的原因是因为它超出了我的控制,xml 将在 utf-8 中) 但!

如果我尝试保存它

<?xml version="1.0"  encoding="UTF-8"?>
<tag> this is a blah</tag>

它会因以下错误而崩溃并烧毁:

XML parsing: line 1, character 39, unable to switch the encoding. Stacktrace follows:
com.microsoft.sqlserver.jdbc.SQLServerException: XML parsing: line 1, character 39, unable to switch the encoding
        at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
        at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
        at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
        at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
        at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
        at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)
        at secMgr.DataService.insertMessage(DataService.groovy:79)
        at secMgr.DataService$_$tt__createTransaction_closure4.doCall(DataService.groovy:142)
        at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:698)
        at secMgr.DataService.$tt__createTransaction(DataService.groovy:140)

真正让我困惑的是,当我尝试通过 Microsoft SQL Server Management Studio 将 UTF-16 编码的 xml 直接插入表中时,我得到了同样的错误:

Msg 9402, Level 16, State 1, Line 1
XML parsing: line 1, character 40, unable to switch the encoding

虽然 UTF-8 编码适用于直接插入。

我觉得我在这里遗漏了一些重要的东西......

【问题讨论】:

标签: xml grails utf-8 sql-server-2012 utf-16


【解决方案1】:

在保存到数据库之前将字符串更改为字节数组解决了这个问题...听起来微不足道,但需要大量的试验和错误。 这是我的示例中的修复: 我的领域类: 类 Message 实现 Serializable{

    long id 
    byte[] message
    String messageType  

    static hasMany = [messageTracker: MessageTracker]

    static constraints = {      
        id nullable: false
        message (nullable: false, maxSize: 2147483646)
        messageType (inList: ["CDM", "MISMO"])      
    }

    static mapping = {
        table 'message'
        version false
        id column: 'message_id', generator: 'identity'
        message column: 'message'
        messageType column: 'message_type'
    }
}

我的服务

private Message insertMessage( String message, String messageType){
        log.info("Inside insertMessage Service")

        Message msg = new Message(message: message.getBytes(), 
                                    messageType: messageType.toUpperCase())

        if(!msg.save()){
            log.error "Trouble saving message" + msg.errors
            throw new ValidationException(msg.errors)
        }

        return msg
    }

请注意,我确实找到了一个“糟糕”的解决方案,我刚刚从消息字符串中删除了包含版本和编码的 xml 标记,我在其中创建了一个持有者字符串,然后使用了这个正则表达式:

message = messageOld.replaceAll(~/<\?xml(.+?)\?>/", "").trim();

根据这个答案how to remove Xml version string from String提出了这个糟糕的解决方案

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2011-01-28
    • 2013-09-09
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    相关资源
    最近更新 更多