【问题标题】:How to allow data truncation in a single DB transaction?如何允许在单个数据库事务中截断数据?
【发布时间】:2012-05-23 04:00:19
【问题描述】:

当插入的数据大于目标列时mysql会抛出错误。总而言之,这似乎是一种积极的行为。

但是,我想在一个特定交易期间取消此行为 - 在此交易中,如果数据太大,我希望发生截断。

有没有办法禁用此行为,但仅限于一个事务?这是the documentation 在 JDBC 级别的说明:

从 Connector/J 3.1.0 开始,JDBC 驱动程序会发出警告或 按照 JDBC 的要求抛出 DataTruncation 异常 规范,除非连接被配置为不这样做 使用属性 jdbcCompliantTruncation 并将其设置为 false。

【问题讨论】:

    标签: mysql jpa playframework playframework-1.x


    【解决方案1】:

    行为取决于 MySQL 会话变量 sql_mode。您可以在连接期间更改变量,稍后将其重置为原始值。在我的系统上,sql_mode 的默认值为:

    SELECT @@sql_mode;
    -- REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI,NO_AUTO_VALUE_ON_ZERO,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
    

    您可以在程序中解析此结果,删除项目STRICT_ALL_TABLES,使用SET SESSION sql_mode='...' 更新值,执行语句并在事务结束时重置变量。

    @ripper234 编辑:

    这是我本着这个答案的精神编写的代码:

    private static final disableMysqlStrictMode = 
        ((String)Play.configuration.get("db.url")).contains("mysql://");
    
    ...
    
    String originalSqlMode = null;
    try {
        if (disableMysqlStrictMode) {
            // Strip away mysql's "strict mode" for this transaction - in case one of the columns is truncated, we don't want the entire tx to fail
            // http://stackoverflow.com/a/10606085/11236
            Query query = JPA.em().createNativeQuery("SELECT @@sql_mode;");
            originalSqlMode = (String)query.getSingleResult();
            String newSqlMode = originalSqlMode
                .replace("STRICT_ALL_TABLES", "")
                .replace("STRICT_TRANS_TABLES", "")
                .replace(",,", ",");
            JPA.em().createNativeQuery("SET SESSION sql_mode=?").setParameter(1, newSqlMode).executeUpdate();
        }
    
    
        // Save my entity here
        obj.save();
    
    
    } finally {
        if (originalSqlMode != null) {
            // Restore original sql_mode
            JPA.em().createNativeQuery("SET SESSION sql_mode=?").setParameter(1, originalSqlMode).executeUpdate();
        }
    }
    

    如果有人愿意,它可以包装成更漂亮的形式。

    【讨论】:

    • 谢谢,我编辑了您的答案以包含我最终使用的代码。
    猜你喜欢
    • 2011-11-17
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 2018-04-01
    • 1970-01-01
    • 2012-06-09
    • 2016-09-27
    相关资源
    最近更新 更多