给jdbc sink中的问号赋值
import com.atguigu.bean.Transientsink;
import com.atguigu.common.GmallConfig;
import lombok.SneakyThrows;
import org.apache.flink.connector.jdbc.JdbcConnectionOptions;
import org.apache.flink.connector.jdbc.JdbcExecutionOptions;
import org.apache.flink.connector.jdbc.JdbcSink;
import org.apache.flink.connector.jdbc.JdbcStatementBuilder;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class MyClickHouseUtil {
//第一个T:声明第二个T是个泛型,而不是有个JavaBean叫T
//第二个T:输入数据类型,因为是工具类所以使用T泛型
public static <T> SinkFunction<T> getSink(String sql){
return JdbcSink.sink(sql,
new JdbcStatementBuilder<T>() {
@SneakyThrows
@Override
//preparedStatement是预编译结果 t是每一行数据,是泛型对象(没有get,set方法)
public void accept(PreparedStatement preparedStatement, T t) throws SQLException {
//通过反射获取所有字段
Class<?> clz = t.getClass(); //先拿到类
Field[] declaredFields = clz.getDeclaredFields(); //通过类拿到所有字段
int offset = 0;
for (int i = 0; i < declaredFields.length; i++) {
//todo 正常调用:对象.字段(XXX) Object value = obj.getXXX();
// 反射:字段(XXX).对象 Object value = XXX.get(obj);
//方法(XXXX)调用: Object value = obj.XXXX(a,b,c);
//invoke(T t,Object...)
//方法(XXXX)反射调用: Object value = XXXX.invoke(obj,a,b,c);
//遍历拿到每一个字段
Field field = declaredFields[i];
field.setAccessible(true);
//获取注解
Transientsink transientsink = field.getAnnotation(Transientsink.class);
if (transientsink != null){
offset++;
continue;
}
Object value = field.get(t);
//index在jdbc中都是以1开头,所以需要+1
preparedStatement.setObject(i+1-offset,value);
//preparedStatement.setObject(i+1,value);
}
}
},
new JdbcExecutionOptions.Builder()
.withBatchIntervalMs(1000)
.withBatchSize(5)
.build(),
new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
.withDriverName(GmallConfig.CLICKHOUSE_DRIVER)
.withUrl(GmallConfig.CLICKHOUSE_URL)
.build());
}
}