All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.guerlab.cloud.server.service.orm.BaseOrmServiceImpl Maven / Gradle / Ivy

There is a newer version: 2024.10.7
Show newest version
/*
 * Copyright 2018-2024 guerlab.net and other contributors.
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.gnu.org/licenses/lgpl-3.0.html
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.guerlab.cloud.server.service.orm;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import net.guerlab.cloud.commons.entity.IBaseEntity;
import net.guerlab.cloud.core.result.Pageable;
import net.guerlab.cloud.core.sequence.Sequence;
import net.guerlab.cloud.searchparams.SearchParams;
import net.guerlab.cloud.server.utils.BatchSaveUtils;
import net.guerlab.cloud.server.utils.PageUtils;
import net.guerlab.commons.collection.CollectionUtil;

/**
 * 基本ORM服务实现.
 *
 * @param  数据类型
 * @param  Mapper类型
 * @param  搜索参数类型
 * @author guer
 */
@SuppressWarnings({"unused", "EmptyMethod"})
@Slf4j
@Validated
public abstract class BaseOrmServiceImpl, Q extends SearchParams>
		implements BaseOrmService {

	/**
	 * 默认单次操作数量.
	 */
	protected static final int DEFAULT_BATCH_SIZE = 1000;

	private static final Log ORM_LOGGER = LogFactory.getLog(BaseOrmServiceImpl.class);

	/**
	 * 实体类型.
	 */
	protected final Class entityClass = this.currentModelClass();

	/**
	 * mapper类型.
	 */
	protected final Class mapperClass = this.currentMapperClass();

	/**
	 * 序列.
	 */
	protected final Sequence sequence;

	/**
	 * mapper.
	 */
	protected final M baseMapper;

	@Resource
	private SqlSessionFactory sqlSessionFactory;

	protected BaseOrmServiceImpl(Sequence sequence, M baseMapper) {
		this.sequence = sequence;
		this.baseMapper = baseMapper;
	}

	/**
	 * 获取mapper.
	 *
	 * @return mapper
	 */
	public final M getBaseMapper() {
		return this.baseMapper;
	}

	@Override
	public E selectOne(E entity) {
		QueryWrapper queryWrapper = getQueryWrapper();
		queryWrapper.setEntity(entity);
		E result = getBaseMapper().selectOne(queryWrapper);
		if (result != null) {
			afterSelect(Collections.singleton(result), null);
		}
		return result;
	}

	@Override
	public E selectOne(Q searchParams) {
		E result = getBaseMapper().selectOne(getQueryWrapperWithSelectMethod(searchParams));
		if (result != null) {
			afterSelect(Collections.singleton(result), null);
		}
		return result;
	}

	@Nullable
	@Override
	public E selectById(Long id) {
		E result = getBaseMapper().selectById(id);
		if (result != null) {
			afterSelect(Collections.singleton(result), null);
		}
		return result;
	}

	@Override
	public List selectByIds(List ids) {
		ids = ids.stream().filter(Objects::nonNull).distinct().toList();
		if (ids.isEmpty()) {
			return Collections.emptyList();
		}
		List list = getBaseMapper().selectBatchIds(ids);
		if (!list.isEmpty()) {
			afterSelect(list, null);
		}
		return list;
	}

	@Override
	public List selectList(Q searchParams) {
		if (!beforeSelect(searchParams)) {
			return Collections.emptyList();
		}
		QueryWrapper queryWrapper = getQueryWrapperWithSelectMethod(searchParams);
		List list = getBaseMapper().selectList(queryWrapper);
		if (!list.isEmpty()) {
			afterSelect(list, searchParams);
		}
		return list;
	}

	@Override
	public Pageable selectPage(Q searchParams, int pageId, int pageSize) {
		if (!beforeSelect(searchParams)) {
			return Pageable.empty();
		}
		Pageable result = PageUtils.selectPage(this, searchParams, pageId, pageSize, getBaseMapper());
		if (!result.getList().isEmpty()) {
			afterSelect(result.getList(), searchParams);
		}
		return result;
	}

	@SuppressWarnings({"BooleanMethodIsAlwaysInverted", "SameReturnValue"})
	protected boolean beforeSelect(Q searchParams) {
		return true;
	}


	protected void afterSelect(Collection items, @Nullable Q searchParams) {

	}

	@Override
	public long selectCount(Q searchParams) {
		Long result = getBaseMapper().selectCount(getQueryWrapperWithSelectMethod(searchParams));
		return result == null ? 0 : result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public E insert(E entity) {
		entity.id(null);
		insertBefore(entity);
		getBaseMapper().insert(entity);
		insertAfter(entity);
		return entity;
	}

	/**
	 * 添加前.
	 *
	 * @param entity 实体
	 */
	protected void insertBefore(E entity) {
		/* 默认空实现 */
	}

	/**
	 * 添加后.
	 *
	 * @param entity 实体
	 */
	protected void insertAfter(E entity) {
		/* 默认空实现 */
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List batchInsert(Collection collection, boolean ignoreBeforeCheckException) {
		List list = BatchSaveUtils.filter(collection, item -> batchSaveBefore(item, ignoreBeforeCheckException));

		if (CollectionUtil.isNotEmpty(list)) {
			saveBatch(list, DEFAULT_BATCH_SIZE);
		}

		return list;
	}

	/**
	 * 保存检查.
	 *
	 * @param entity                     实体
	 * @param ignoreBeforeCheckException 是否忽略前置检查异常
	 * @return 如果返回null则不保存该对象,否则保存该对象
	 */
	@Nullable
	protected E batchSaveBefore(E entity, boolean ignoreBeforeCheckException) {
		try {
			insertBefore(entity);
			return entity;
		}
		catch (Exception e) {
			log.debug(e.getMessage(), e);
			if (ignoreBeforeCheckException) {
				return null;
			}
			throw e;
		}
	}

	/**
	 * 批量保存.
	 *
	 * @param entities  实体列表
	 * @param batchSize 单次操作数量
	 */
	@SuppressWarnings("SameParameterValue")
	protected final void saveBatch(Collection entities, int batchSize) {
		String sqlStatement = SqlHelper.getSqlStatement(this.mapperClass, SqlMethod.INSERT_ONE);
		this.executeBatch(entities, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
	}

	/**
	 * 批量执行.
	 *
	 * @param list      实体列表
	 * @param batchSize 单次执行数量
	 * @param consumer  操作内容
	 */
	protected void executeBatch(Collection list, int batchSize, BiConsumer consumer) {
		SqlHelper.executeBatch(sqlSessionFactory, ORM_LOGGER, list, batchSize, consumer);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateById(E entity) {
		updateBefore(entity);
		int result = getBaseMapper().updateById(entity);
		updateAfter(entity);
		return result > 0;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean update(E entity, Q searchParams) {
		return getBaseMapper().update(entity, getQueryWrapper(searchParams)) > 0;
	}

	/**
	 * 更新前.
	 *
	 * @param entity 实体
	 */
	protected void updateBefore(E entity) {
		/* 默认空实现 */
	}

	/**
	 * 更新后.
	 *
	 * @param entity 实体
	 */
	protected void updateAfter(E entity) {
		/* 默认空实现 */
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List batchUpdateById(Collection collection, boolean ignoreBeforeCheckException) {
		List list = BatchSaveUtils.filter(collection, item -> batchUpdateBefore(item, ignoreBeforeCheckException));

		if (CollectionUtil.isNotEmpty(list)) {
			updateBatch(list, DEFAULT_BATCH_SIZE);
		}

		return list;
	}

	/**
	 * 更新检查.
	 *
	 * @param entity                     实体
	 * @param ignoreBeforeCheckException 是否忽略前置检查异常
	 * @return 如果返回null则不保存该对象,否则保存该对象
	 */
	@Nullable
	protected E batchUpdateBefore(E entity, boolean ignoreBeforeCheckException) {
		try {
			updateBefore(entity);
			return entity;
		}
		catch (Exception e) {
			log.debug(e.getMessage(), e);
			if (ignoreBeforeCheckException) {
				return null;
			}
			throw e;
		}
	}

	/**
	 * 批量更新.
	 *
	 * @param entities  实体列表
	 * @param batchSize 单次操作数量
	 */
	@SuppressWarnings("SameParameterValue")
	protected final void updateBatch(Collection entities, int batchSize) {
		String sqlStatement = SqlHelper.getSqlStatement(this.mapperClass, SqlMethod.UPDATE_BY_ID);
		this.executeBatch(entities, batchSize, (sqlSession, entity) -> {
			MapperMethod.ParamMap param = new MapperMethod.ParamMap<>();
			param.put("et", entity);
			sqlSession.update(sqlStatement, param);
		});
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public E saveOrUpdate(E entity) {
		Long id = entity.id();
		if (id == null) {
			return insert(entity);
		}

		updateById(entity);
		return selectById(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List batchSaveOrUpdate(Collection list, boolean ignoreBeforeCheckException) {
		list = list.stream().filter(Objects::nonNull).toList();
		if (list.isEmpty()) {
			return Collections.emptyList();
		}

		List result = new ArrayList<>(list.size());
		Map> groupMap = list.stream().collect(Collectors.groupingBy(entity -> entity.id() == null));
		List needAdds = groupMap.getOrDefault(true, Collections.emptyList());
		List needUpdates = groupMap.getOrDefault(false, Collections.emptyList());

		if (!needAdds.isEmpty()) {
			result.addAll(batchInsert(needAdds, ignoreBeforeCheckException));
		}
		if (!needUpdates.isEmpty()) {
			result.addAll(batchUpdateById(needUpdates, ignoreBeforeCheckException));
		}

		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(Q searchParams) {
		deleteBefore(searchParams);
		QueryWrapper queryWrapper = getQueryWrapper(searchParams);
		getBaseMapper().delete(queryWrapper);
		deleteAfter(searchParams);
	}

	/**
	 * 删除前.
	 *
	 * @param searchParams 搜索参数
	 */
	protected void deleteBefore(Q searchParams) {
		/* 默认空实现 */
	}

	/**
	 * 删除后.
	 *
	 * @param searchParams 搜索参数
	 */
	protected void deleteAfter(Q searchParams) {
		/* 默认空实现 */
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteById(Long id) {
		deleteByIdBefore(id);
		getBaseMapper().deleteById(id);
		deleteByIdAfter(id);
	}

	/**
	 * 删除前.
	 *
	 * @param id id
	 */
	protected void deleteByIdBefore(Long id) {
		/* 默认空实现 */
	}

	/**
	 * 删除后.
	 *
	 * @param id id
	 */
	protected void deleteByIdAfter(Long id) {
		/* 默认空实现 */
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(LambdaQueryWrapper queryWrapper) {
		getBaseMapper().delete(queryWrapper);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(QueryWrapper queryWrapper) {
		getBaseMapper().delete(queryWrapper);
	}

	/**
	 * 获取当前mapper对象类型.
	 *
	 * @return mapper对象类型
	 */
	@SuppressWarnings("unchecked")
	protected Class currentMapperClass() {
		return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseOrmServiceImpl.class, 1);
	}

	/**
	 * 获取当前模型对象类型.
	 *
	 * @return 模型对象类型
	 */
	@SuppressWarnings("unchecked")
	protected Class currentModelClass() {
		return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseOrmServiceImpl.class, 0);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy