Skip to content

Commit

Permalink
Merge branch 'release/v3.4-RC1'
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Chan committed Oct 20, 2024
2 parents 9b21b22 + 26b1a75 commit b4a3ebe
Show file tree
Hide file tree
Showing 17 changed files with 944 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ public Optional<T> findOneById(ID id) {

@Override
public boolean existsById(ID id) {
return findOneById(id).isPresent();
QueryWrapper<T> wrapper = new QueryWrapper<>();
TableInfo tableInfo = getTableInfo();
wrapper.eq(tableInfo.getKeyColumn(), id);
return getBaseMapper().selectCount(wrapper) > 0;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2024. ChenJun ([email protected] & https://github.com/John-Chan)
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.power4j.fist.boot.mybaits.migrate;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.power4j.fist.boot.mybaits.crud.repository.Repository;

import java.io.Serializable;
import java.util.Collection;
import java.util.function.BiConsumer;

/**
* @author CJ ([email protected])
* @since 1.0
*/
public class BatchColumnResolver<T> implements BatchUniqueResolver<T> {

private final Repository<T, ? extends Serializable> repository;

private final BiConsumer<Collection<T>, LambdaQueryWrapper<T>> queryBuilder;

public static <T> BatchColumnResolver<T> of(Repository<T, ? extends Serializable> repository,
BiConsumer<Collection<T>, LambdaQueryWrapper<T>> queryBuilder) {
return new BatchColumnResolver<>(repository, queryBuilder);
}

public BatchColumnResolver(Repository<T, ? extends Serializable> repository,
BiConsumer<Collection<T>, LambdaQueryWrapper<T>> queryBuilder) {
this.queryBuilder = queryBuilder;
this.repository = repository;
}

@Override
public long exists(Collection<T> data) {
return repository.countBy(applyQuery(data));
}

@Override
public void removeExists(Collection<T> data) {
repository.deleteAllBy(applyQuery(data));
}

protected LambdaQueryWrapper<T> applyQuery(Collection<T> example) {
LambdaQueryWrapper<T> queryWrapper = repository.lambdaWrapper();
queryBuilder.accept(example, queryWrapper);
return queryWrapper;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright 2024. ChenJun ([email protected] & https://github.com/John-Chan)
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.power4j.fist.boot.mybaits.migrate;

import com.power4j.fist.boot.mybaits.crud.repository.Repository;
import com.power4j.fist.data.migrate.ImportDataHandler;
import com.power4j.fist.data.migrate.ImportStatistic;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;

/**
* @author CJ ([email protected])
* @since 1.0
*/
@Slf4j
public class BatchImportPipeline<P, T, ID extends Serializable> implements ImportDataHandler<P> {

private final UniqueResolveEnum uniqueResolve;

private final BatchUniqueResolver<T> uniqueResolver;

private final Repository<T, ID> repository;

private final Function<P, T> mapper;

private final boolean cleanAll;

private final long maxImportCount;

private final ImportStatistic statistic = ImportStatistic.empty();

public BatchImportPipeline(UniqueResolveEnum uniqueResolve, BatchUniqueResolver<T> uniqueResolver,
Repository<T, ID> repository, Function<P, T> mapper, boolean cleanAll, long maxImportCount) {
if (!cleanAll && uniqueResolve == UniqueResolveEnum.SKIP) {
throw new IllegalArgumentException("cleanAll must be true when uniqueResolve is SKIP");
}
this.uniqueResolve = uniqueResolve;
this.uniqueResolver = uniqueResolver;
this.repository = repository;
this.mapper = mapper;
this.cleanAll = cleanAll;
this.maxImportCount = maxImportCount;
}

@Override
public void accept(Collection<P> data) {
final int size = data.size();
if (log.isDebugEnabled()) {
log.debug("receive data,count :{},total :{}", size, statistic.getReceiveCount());
}
statistic.addReceiveCount(size);
handleData(data);
}

private void handleData(Collection<P> data) {
// 批量模式下不进行精确控制条数
if (statistic.getInsertCount() >= maxImportCount && maxImportCount > 0) {
log.info("Import max count reached: {},skip", maxImportCount);
return;
}
long existCount;
List<T> entities = data.stream().map(mapper).toList();
int skipCount = 0;
int deleteCount = 0;
if (!cleanAll && (existCount = uniqueResolver.exists(entities)) > 0L) {
switch (uniqueResolve) {
case SKIP:
skipCount = (int) existCount;
break;
case REMOVE:
uniqueResolver.removeExists(entities);
deleteCount = (int) existCount;
break;
default:
throw new IllegalStateException("Unsupported unique resolve: " + uniqueResolve);
}
}
repository.saveAll(entities);
statistic.addSkipCount(skipCount);
statistic.addDeleteCount(deleteCount);
statistic.addInsertCount(entities.size() - skipCount);
}

@Override
public ImportStatistic statistic() {
return statistic;
}

@Override
public void beforeAll() {
statistic.reset();
if (cleanAll) {
long deleteCount = repository.countAll();
repository.deleteAll();
statistic.setDeleteCount(deleteCount);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2024. ChenJun ([email protected] & https://github.com/John-Chan)
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.power4j.fist.boot.mybaits.migrate;

import java.util.Collection;

/**
* @author CJ ([email protected])
* @since 1.0
*/
public interface BatchUniqueResolver<T> {

/**
* 检测是记录否存在
* @param data 数据
* @return 已经存在数据条数
*/
long exists(Collection<T> data);

/**
* 删除已经存在的记录
* @param data 数据
*/
void removeExists(Collection<T> data);

BatchUniqueResolver<?> INVALID = new BatchUniqueResolver<>() {
@Override
public long exists(Collection<Object> data) {
throw new IllegalStateException("Invalid unique resolver");
}

@Override
public void removeExists(Collection<Object> data) {
throw new IllegalStateException("Invalid unique resolver");
}
};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2024. ChenJun ([email protected] & https://github.com/John-Chan)
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.power4j.fist.boot.mybaits.migrate;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.power4j.fist.boot.mybaits.crud.repository.Repository;

import java.io.Serializable;
import java.util.function.BiConsumer;

/**
* @author CJ ([email protected])
* @since 1.0
*/
public class ColumnResolver<T> implements UniqueResolver<T> {

private final Repository<T, ? extends Serializable> repository;

private final BiConsumer<T, LambdaQueryWrapper<T>> queryBuilder;

public static <T> ColumnResolver<T> of(Repository<T, ? extends Serializable> repository,
BiConsumer<T, LambdaQueryWrapper<T>> queryBuilder) {
return new ColumnResolver<>(repository, queryBuilder);
}

public ColumnResolver(Repository<T, ? extends Serializable> repository,
BiConsumer<T, LambdaQueryWrapper<T>> queryBuilder) {
this.queryBuilder = queryBuilder;
this.repository = repository;
}

@Override
public boolean exists(T example) {
return repository.countBy(applyQuery(example)) > 0;
}

@Override
public void remove(T example) {
repository.deleteAllBy(applyQuery(example));
}

protected LambdaQueryWrapper<T> applyQuery(T example) {
LambdaQueryWrapper<T> queryWrapper = repository.lambdaWrapper();
queryBuilder.accept(example, queryWrapper);
return queryWrapper;
}

}
Loading

0 comments on commit b4a3ebe

Please sign in to comment.