dataX中的writeModel

本文中的writeModel主要是Mysql、Oracle等傳統(tǒng)關(guān)系數(shù)據(jù)庫中的writeMode俄周。dataX導入到hive是直接寫文件吁讨,不會支持這些writeModel。

預(yù)備知識

Mysql中的ON DUPLICATE KEY UPDATE

使用 ON DUPLICATE KEY UPDATE語句的時候峦朗,如果你插入的記錄導致主鍵或唯一索引重復(fù)建丧,那么Mysql就會認為該條記錄存在,則執(zhí)行update語句而不是insert語句波势;反之則執(zhí)行insert語句而不是更新語句翎朱。
新建表user橄维,id作為user的主鍵,并插入一條id = 1的數(shù)據(jù)

CREATE TABLE `user` (
  `id` int(12) NOT NULL ,
  `username` varchar(32) DEFAULT NULL,
  `password` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO user VALUES (1,'GJMZ1','123456');

執(zhí)行以下語句之后user表中然后只有一條語句拴曲,只是將password改為'1234567'争舞,這就是ON DUPLICATE KEY UPDATE的功能。

INSERT INTO user VALUES (1,'GJMZ1','1234567')ON DUPLICATE KEY UPDATE username = 'GJMZ1',password='1234567';

如果去掉表中的主鍵澈灼,執(zhí)行上面兩條sql之后竞川,表中會有兩行數(shù)據(jù),因為執(zhí)行ON DUPLICATE KEY UPDATE語句時蕉汪,mysql是通過主鍵或者唯一索引來判斷兩條數(shù)據(jù)是否重復(fù)流译。

writeModel的用法

writeModel控制寫入數(shù)據(jù)到目標表采用 insert into 或者 replace into 或者 ON DUPLICATE KEY UPDATE 語句逞怨。

  • insert:將數(shù)據(jù)源表的數(shù)據(jù)直接寫的到目的表者疤,主要用于全量的導入。實現(xiàn)原理是直接采用insert into;
  • replace和update:如果目標表中包含待寫入的數(shù)據(jù)則更新該行數(shù)據(jù)叠赦,主要用于增量導入驹马。實現(xiàn)原理:在mysql中用ON DUPLICATE KEY UPDATE語句,其他數(shù)據(jù)庫中用replace into.

相關(guān)源碼

以MysqlWriter為例進行說明除秀。
流程很簡單糯累,設(shè)置的時候用戶配置的每一個字段都要更新,以"?"的方式寫進sql中册踩,最后利用PrepareStatement#setXXX進行設(shè)置泳姐。根據(jù)三種模式拼接相應(yīng)的sql即可,最后將sql保存在Cofiguration#insertOrReplaceTemplate中暂吉。

// OriginalConfPretreatmentUtil#dealWriteMode
public static void dealWriteMode(Configuration originalConfig, DataBaseType dataBaseType) {
        List<String> columns = originalConfig.getList(Key.COLUMN, String.class);
        String jdbcUrl = originalConfig.getString(String.format("%s[0].%s",
                Constant.CONN_MARK, Key.JDBC_URL, String.class));
        // 默認為:insert 方式
        String writeMode = originalConfig.getString(Key.WRITE_MODE, "INSERT");
        List<String> valueHolders = new ArrayList<String>(columns.size());
        for (int i = 0; i < columns.size(); i++) {
            valueHolders.add("?");
        }

        boolean forceUseUpdate = false;
        //ob10的處理
        if (dataBaseType == DataBaseType.MySql && isOB10(jdbcUrl)) {
            forceUseUpdate = true;
        }

        String writeDataSqlTemplate = WriterUtil.getWriteTemplate(columns, valueHolders, writeMode,dataBaseType, forceUseUpdate);
        LOG.info("Write data [\n{}\n], which jdbcUrl like:[{}]", writeDataSqlTemplate, jdbcUrl);
        originalConfig.set(Constant.INSERT_OR_REPLACE_TEMPLATE_MARK, writeDataSqlTemplate);
}
    
// WriterUtil#getWriteTemplate
public static String getWriteTemplate(List<String> columnHolders, List<String> valueHolders, String writeMode, DataBaseType dataBaseType, boolean forceUseUpdate) {
        boolean isWriteModeLegal = writeMode.trim().toLowerCase().startsWith("insert")
                || writeMode.trim().toLowerCase().startsWith("replace")
                || writeMode.trim().toLowerCase().startsWith("update");

        if (!isWriteModeLegal) {
            throw DataXException.asDataXException(DBUtilErrorCode.ILLEGAL_VALUE,
                    String.format("您所配置的 writeMode:%s 錯誤. 因為DataX 目前僅支持replace,update 或 insert 方式. 請檢查您的配置并作出修改.", writeMode));
        }
        // && writeMode.trim().toLowerCase().startsWith("replace")
        String writeDataSqlTemplate;
        if (forceUseUpdate ||
                ((dataBaseType == DataBaseType.MySql || dataBaseType == DataBaseType.Tddl) && writeMode.trim().toLowerCase().startsWith("update"))
                ) {
            //update只在mysql下使用

            writeDataSqlTemplate = new StringBuilder()
                    .append("INSERT INTO %s (").append(StringUtils.join(columnHolders, ","))
                    .append(") VALUES(").append(StringUtils.join(valueHolders, ","))
                    .append(")")
                    .append(onDuplicateKeyUpdateString(columnHolders))
                    .toString();
        } else {

            //這里是保護,如果其他錯誤的使用了update,需要更換為replace
            if (writeMode.trim().toLowerCase().startsWith("update")) {
                writeMode = "replace";
            }
            writeDataSqlTemplate = new StringBuilder().append(writeMode)
                    .append(" INTO %s (").append(StringUtils.join(columnHolders, ","))
                    .append(") VALUES(").append(StringUtils.join(valueHolders, ","))
                    .append(")").toString();
        }

        return writeDataSqlTemplate;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胖秒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子慕的,更是在濱河造成了極大的恐慌阎肝,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肮街,死亡現(xiàn)場離奇詭異风题,居然都是意外死亡,警方通過查閱死者的電腦和手機嫉父,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門沛硅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绕辖,你說我怎么就攤上這事摇肌。” “怎么了引镊?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵朦蕴,是天一觀的道長篮条。 經(jīng)常有香客問我,道長吩抓,這世上最難降的妖魔是什么涉茧? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮疹娶,結(jié)果婚禮上伴栓,老公的妹妹穿的比我還像新娘。我一直安慰自己雨饺,他們只是感情好钳垮,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著额港,像睡著了一般饺窿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上移斩,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天肚医,我揣著相機與錄音,去河邊找鬼向瓷。 笑死肠套,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的猖任。 我是一名探鬼主播你稚,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼朱躺!你這毒婦竟也來了刁赖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤室琢,失蹤者是張志新(化名)和其女友劉穎乾闰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盈滴,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡涯肩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了巢钓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片病苗。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖症汹,靈堂內(nèi)的尸體忽然破棺而出硫朦,到底是詐尸還是另有隱情,我是刑警寧澤背镇,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布咬展,位于F島的核電站泽裳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏破婆。R本人自食惡果不足惜涮总,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祷舀。 院中可真熱鬧瀑梗,春花似錦、人聲如沸裳扯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饰豺。三九已至亿鲜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哟忍,已是汗流浹背狡门。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工陷寝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锅很,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓凤跑,卻偏偏與公主長得像爆安,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仔引,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348