datax之oraclereader读取时间类型字段问题学习

众所周知 hive是字段类型不敏感的,比如date 2022-01-01 和string 2022-01-01 在大多数情况下都是可以呼唤的。我们这边为了方便经常将oracle的date字段 在hive中直接用string字段去替代,最近发现了一个问题。

表中字段如下 字段类型是date。 注意这个date 不是datetime。

 

date类型只保留年月日 不保留时分秒 

所以我们一般来说看到这个date 数值就是年月日,但是因为工具看到的也不同 我用dbeaver看到的如上,同事用的哪个工具忘了如下

当然 我猜测底层存储的肯定是1469635200000 这种,时分秒的单位都归0了

这时候我们要明确一个问题,前端需要看到的到底是什么? 如果你想看到年月日时分秒,那么datax就是这么做的。

但是如果你想看到的只是年月日,那么就需要自己去改了。当然你在hive用date类型接受也没有问题。

学习一下源码。

CommonRdbmsReader.java

// for mysql bug, see http://bugs.mysql.com/bug.php?id=35115
--你看这里还有bug。。 这里才是 年月日 没有时分秒
case Types.DATE:
    if (metaData.getColumnTypeName(i).equalsIgnoreCase("year")) {
        record.addColumn(new LongColumn(rs.getInt(i)));
    } else {
        record.addColumn(new DateColumn(rs.getDate(i)));
    }
    break;

case Types.TIMESTAMP:
    record.addColumn(new DateColumn(rs.getTimestamp(i)));
    break;

注意 oracle的date类型属于这里的 Types.TIMESTAMP 

 DateColumn.java

/**
 * 构建值为ts(java.sql.Timestamp)的DateColumn,使用Date子类型为DATETIME
 * */
public DateColumn(final java.sql.Timestamp ts) {
   this(ts == null ? null : ts.getTime());
   this.setSubType(DateType.DATETIME);
}

设置datecolumn的类型为datetime, 并且把值ts 传进去了。

然后我们看取出来是怎么取的

@Override
public String asString() {
   try {
      return ColumnCast.date2String(this);
   } catch (Exception e) {
      throw DataXException.asDataXException(
            CommonErrorCode.CONVERT_NOT_SUPPORT,
            String.format("Date[%s]类型不能转为String .", this.toString()));
   }
}

@Override
public Date asDate() {
   if (null == this.getRawData()) {
      return null;
   }

   return new Date((Long)this.getRawData());
}
---这里就是as string的后续方法
static String asString(final DateColumn column) {
   if (null == column.asDate()) {
      return null;
   }

   switch (column.getSubType()) {
   case DATE:
      return DateFormatUtils.format(column.asDate(), DateCast.dateFormat,
            DateCast.timeZoner); --yyyy-MM-dd
   case TIME:
      return DateFormatUtils.format(column.asDate(), DateCast.timeFormat,
            DateCast.timeZoner);
   case DATETIME:
      return DateFormatUtils.format(column.asDate(),
            DateCast.datetimeFormat, DateCast.timeZoner);--yyyy-MM-dd HH:mm:ss
   default:
      throw DataXException
            .asDataXException(CommonErrorCode.CONVERT_NOT_SUPPORT,
                  "时间类型出现不支持类型,目前仅支持DATE/TIME/DATETIME。该类型属于编程错误,请反馈给DataX开发团队 .");
   }
}

所以问题很清楚了,

就是oracle对于date类型数据 在java的types里对应的是timestamp

对于mysql的date类型来说对应的就是date 只保留年月日。

这里有点不是特别理解,oracle的date和mysql的date哪里不一样?

CREATE TABLE test.cc_test_time(
t1 DATE,
t2 timestamp
)

String querySql = "SELECT * from test.cc_test_time "; rs = demo.execQuery(querySql); ResultSetMetaData metaData = rs.getMetaData(); for (int i = 1; i <= metaData.getColumnCount(); i++) { System.out.println("columntype="+metaData.getColumnType(i)); }

INSERT INTO test.cc_test_time VALUES (sysdate,sysdate)

columntype=93
columntype=93

而且经过我的测试 oracle的date 和timestamp类型 对应的都是 93也就是timestamp,所以datax在对oracle取数的时候,这两个类型是区分不了的。。

具体我就不尝试了。比如timestamp精确到毫秒 ,我猜测datax也忽略了毫秒,反正统一都是年于日时分秒。 

---------------------------

又遇到一个问题。datax读取oracle的number字段 不是number(22,8)这种会出现问题。

jdbc查询

 datax

datax这里读取的时候直接就rs.getString 最后结果就是科学计数法。。。。 唉 大坑,解决办法也很简单 getBigdecimal或者getObject 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值