【问题标题】:Why Kafka jdbc connect insert data as BLOB instead of varchar为什么Kafka jdbc连接插入数据作为BLOB而不是varchar
【发布时间】:2018-06-21 19:19:36
【问题描述】:

我正在使用 Java 生产者在我的 Kafka 主题顶部插入数据。然后我使用 Kafka jdbc connect 将数据插入到我的 Oracle 表中。下面是我的生产者代码。

package producer.serialized.avro;

import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;


public class Sender4 {

    public static void main(String[] args) {

        String flightSchema = "{\"type\":\"record\"," + "\"name\":\"Flight\","

                + "\"fields\":[{\"name\":\"flight_id\",\"type\":\"string\"},{\"name\":\"flight_to\",\"type\":\"string\"},{\"name\":\"flight_from\",\"type\":\"string\"}]}";                

        Properties props = new Properties();

        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.0.1:9092");
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,io.confluent.kafka.serializers.KafkaAvroSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,io.confluent.kafka.serializers.KafkaAvroSerializer.class);    
        props.put("schema.registry.url", "http://192.168.0.1:8081");            

        KafkaProducer producer = new KafkaProducer(props);    

        Schema.Parser parser = new Schema.Parser();

        Schema schema = parser.parse(flightSchema);            

        GenericRecord avroRecord = new GenericData.Record(schema);

        avroRecord.put("flight_id", "myflight");
        avroRecord.put("flight_to", "QWE");
        avroRecord.put("flight_from", "RTY");    

        ProducerRecord<String, GenericRecord> record = new ProducerRecord<>("topic9",avroRecord);

        producer.send(record);
    }
}

以下是我的 Kafka 连接属性

name=test-sink-6
connector.class=io.confluent.connect.jdbc.JdbcSinkConnector
tasks.max=1
topics=topic9
connection.url=jdbc:oracle:thin:@192.168.0.1:1521:usera
connection.user=usera
connection.password=usera
auto.create=true
table.name.format=FLIGHTS4
key.converter=io.confluent.connect.avro.AvroConverter
key.converter.schema.registry.url=http://192.168.0.1:8081
value.converter=io.confluent.connect.avro.AvroConverter
value.converter.schema.registry.url=http://192.168.0.1:8081

从我的架构中,我希望插入到我的 Oracle 表中的值是 varchar2。我创建了一个包含 3 个 varchar2 列的表。当我启动连接器时,没有插入任何东西。然后我删除了表并在表自动创建模式下运行连接器。那时,创建了表并插入了值。但问题是,列数据类型是 CLOB。我希望它是 varchar2,因为它使用的数据更少。

为什么会发生这种情况,我该如何解决?谢谢你。

【问题讨论】:

    标签: oracle jdbc apache-kafka apache-kafka-connect confluent-platform


    【解决方案1】:

    看起来 Kafka 的 String 映射到 Oracle 的 NCLOB:

    <table border="1">
    <tr>
    <th>Schema Type</th><th>MySQL</th><th>Oracle</th><th>PostgreSQL</th><th>SQLite</th>
    </tr>
    <tr>
    <td>INT8</td><td>TINYINT</td><td>NUMBER(3,0)</td><td>SMALLINT</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>INT16</td><td>SMALLINT</td><td>NUMBER(5,0)</td><td>SMALLINT</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>INT32</td><td>INT</td><td>NUMBER(10,0)</td><td>INT</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>INT64</td><td>BIGINT</td><td>NUMBER(19,0)</td><td>BIGINT</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>FLOAT32</td><td>FLOAT</td><td>BINARY_FLOAT</td><td>REAL</td><td>REAL</td>
    </tr>
    <tr>
    <td>FLOAT64</td><td>DOUBLE</td><td>BINARY_DOUBLE</td><td>DOUBLE PRECISION</td><td>REAL</td>
    </tr>
    <tr>
    <td>BOOLEAN</td><td>TINYINT</td><td>NUMBER(1,0)</td><td>BOOLEAN</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>STRING</td><td>VARCHAR(256)</td><td>NCLOB</td><td>TEXT</td><td>TEXT</td>
    </tr>
    <tr>
    <td>BYTES</td><td>VARBINARY(1024)</td><td>BLOB</td><td>BYTEA</td><td>BLOB</td>
    </tr>
    <tr>
    <td>'Decimal'</td><td>DECIMAL(65,s)</td><td>NUMBER(*,s)</td><td>DECIMAL</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>'Date'</td><td>DATE</td><td>DATE</td><td>DATE</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>'Time'</td><td>TIME(3)</td><td>DATE</td><td>TIME</td><td>NUMERIC</td>
    </tr>
    <tr>
    <td>'Timestamp'</td><td>TIMESTAMP(3)</td><td>TIMESTAMP</td><td>TIMESTAMP</td><td>NUMERIC</td>
    </tr>
    </table>

    来源:https://www.ibm.com/support/knowledgecenter/en/SSPT3X_4.2.5/com.ibm.swg.im.infosphere.biginsights.admin.doc/doc/admin_kafka_jdbc_sink.html

    https://docs.confluent.io/current/connect/connect-jdbc/docs/sink_connector.html

    更新

    OracleDialect 类 (https://github.com/confluentinc/kafka-connect-jdbc/blob/master/src/main/java/io/confluent/connect/jdbc/sink/dialect/OracleDialect.java) 已硬编码 CLOB 值,只需使用您自己的类扩展它并更改映射将无济于事,因为在 JdbcSinkTask (https://github.com/confluentinc/kafka-connect-jdbc/blob/master/src/main/java/io/confluent/connect/jdbc/sink/JdbcSinkTask.java 的静态方法中定义了方言类型)

    final DbDialect dbDialect = DbDialect.fromConnectionString(config.connectionUrl);
    

    【讨论】:

    • 好的,我明白了。是否有任何选项可以自定义/覆盖它?
    • @blasteralfredΨ,我认为唯一的方法是实现自己的OracleJDBCSync,这将VARCHAR 而不是CLOB
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 2015-08-10
    • 2017-11-30
    • 2021-03-17
    • 2012-11-03
    • 2014-08-10
    相关资源
    最近更新 更多