
com.huaweicloud.dws.client.model.Record Maven / Gradle / Ivy
package com.huaweicloud.dws.client.model;
import com.huaweicloud.dws.client.TableConfig;
import com.huaweicloud.dws.client.exception.InvalidException;
import com.huaweicloud.dws.client.op.IConvert;
import com.huaweicloud.dws.client.util.AssertUtil;
import java.io.Serializable;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
/**
* @ProjectName: dws-connector
* @ClassName: Record
* @Description: 操作记录定义
* @Date: 2022/12/22 18:25
* @Version: 1.0
*/
public class Record implements Serializable {
public static final int EMPTY = -1;
private final TableSchema schema;
private OperationType type = OperationType.WRITE;
private TableConfig config;
/**
* 唯一KEY,避免去重时多次执行
*/
private Record keyRecord;
/**
* 记录每条数据值
*/
private final Object[] values;
/**
* 记录被设置过的列
*/
private final BitSet columnBit;
/**
* 记录需要忽略更新的列
*/
private final BitSet ignoreUpdate;
private BitSet compareField;
private IConvert dataConvert;
/**
* 生成该记录的数据库唯一key
*/
public synchronized Record getRecordKey() {
if (this.keyRecord != null) {
return keyRecord;
}
keyRecord = new Record(schema, type, null);
keyRecord.type = this.type;
// 如果没有主键或者没设置主键(可能数据库自增),则不存在更新问题,有主键则提取主键字段
if (!isUpsert()) {
return this;
}
List keyNames = schema.getKeyIndexList();
for (Integer index : keyNames) {
keyRecord.setValue(index, values[index]);
}
return keyRecord;
}
/**
* 检查是否是走upsert
* 无主键或者自增主键返回 false
* @return
*/
public boolean isUpsert() {
List keys = schema.getKeyIndexList();
// 没有设置主键时 需要保证是自增主键才能正常入库
return !keys.isEmpty() && EMPTY != (keys.stream().filter(this::isSet).findAny().orElse(EMPTY));
}
public BitSet getColumnBit() {
return columnBit;
}
public BitSet getIgnoreUpdate() {
return ignoreUpdate;
}
public OperationType getType() {
return type;
}
public Record(TableSchema schema) {
if (schema == null) {
throw new InvalidException("schema is null");
}
this.schema = schema;
columnBit = new BitSet(schema.getColumns().size());
ignoreUpdate = new BitSet(schema.getColumns().size());
values = new Object[schema.getColumns().size()];
}
public Record(TableSchema schema, OperationType type) {
this(schema, type, null);
}
public Record(TableSchema schema, OperationType type, TableConfig config) {
this(schema);
if (type == null) {
throw new InvalidException("operation type is null");
}
this.type = type;
this.config = config;
if (config != null) {
if (this.config.getCompareField() != null) {
this.compareField = new BitSet(schema.getColumns().size());
for (String key : this.config.getCompareField()) {
Integer index = this.schema.getColumnIndex(key);
compareField.set(index);
}
}
}
}
public Record(TableSchema schema, OperationType type, TableConfig config, Object[] values, BitSet columnBit, BitSet ignoreUpdate, IConvert convert) {
this.dataConvert = convert;
this.schema = schema;
if (values.length > schema.getColumns().size()) {
throw new InvalidException("values length must more dws table columns size");
}
this.columnBit = columnBit;
this.ignoreUpdate = ignoreUpdate;
if (this.schema.getColumns().size() == values.length) {
this.values = values;
} else {
this.values = new Object[schema.getColumns().size()];
System.arraycopy(values, 0, this.values, 0, values.length);
}
if (type == null) {
throw new InvalidException("operation type is null");
}
this.type = type;
this.config = config;
if (config != null) {
if (this.config.getCompareField() != null) {
this.compareField = new BitSet(schema.getColumns().size());
for (String key : this.config.getCompareField()) {
Integer index = this.schema.getColumnIndex(key);
compareField.set(index);
}
}
}
}
public TableSchema getTableSchema() {
return schema;
}
public Record setValue(int i, Object value) {
return this.setValue(i, value, false);
}
public Record setValue(String columnName, Object value, boolean ignoreUpdate) {
return setValue(getAndCheckIndex(columnName), value, ignoreUpdate);
}
public Record setValue(int i, Object value, boolean ignoreUpdate) {
values[i] = value;
columnBit.set(i);
if (ignoreUpdate) {
this.ignoreUpdate.set(i);
}
return this;
}
public Object getValue(int i) {
return values[i];
}
public Object getValue(String columnName) {
return getValue(getAndCheckIndex(columnName));
}
private Integer getAndCheckIndex(String columnName) {
Integer index = schema.getColumnIndex(columnName);
checkIdx(index);
return index;
}
public boolean isSet(String name) {
Integer i = getAndCheckIndex(name);
return columnBit.get(i);
}
public boolean isSet(int index) {
return columnBit.get(index);
}
public boolean isIgnoreUpdate(String name) {
Integer i = getAndCheckIndex(name);
return ignoreUpdate.get(i);
}
private void checkIdx(int i) {
AssertUtil.isTrue(i < values.length && i >= 0, new InvalidException("not allowed i " + i));
}
/**
* 用record中被设置的字段覆盖当前数据的对应字段
*/
public void cover(Record record) {
if (!schema.equals(record.schema)) {
throw new InvalidException("schema not match");
}
if (compareField != null) {
long count = compareField.stream().mapToObj(e -> {
Object value = record.getValue(e);
Object oldValue = this.getValue(e);
return (value instanceof Comparable) && oldValue != null && ((Comparable) value).compareTo(oldValue) > 0;
}).filter(x -> !x).count();
if (count != 0) {
// 当前值不比原有值大,忽略
return;
}
}
record.columnBit.stream().forEach(e -> {
if (!record.ignoreUpdate.get(e)) {
// 如果第二次数据标记冲突时忽略更新,则丢弃该字段二次数据
this.setValue(e, record.getValue(e), record.ignoreUpdate.get(e));
}
});
}
public Record(TableSchema schema, OperationType type, Object[] values, BitSet columnBit,
BitSet ignoreUpdate) {
this.schema = schema;
this.type = type;
this.values = values;
this.columnBit = columnBit;
this.ignoreUpdate = ignoreUpdate;
}
public Record copy() {
return new Record(
this.schema,
this.type,
this.values.clone(),
(BitSet) this.columnBit.clone(),
(BitSet) this.ignoreUpdate.clone());
}
public IConvert getDataConvert() {
return dataConvert;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (!(o instanceof Record)) {
return false;
}
return Arrays.deepEquals(this.values, ((Record) o).values);
}
@Override
public int hashCode() {
return Arrays.deepHashCode(this.values);
}
@Override
public String toString() {
return "Record{" +
"schema=" + schema +
", values=" + Arrays.toString(values) +
", columnBit=" + columnBit +
", ignoreUpdate=" + ignoreUpdate +
'}';
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy