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

lodsve.mybatis.utils.VersionUtils Maven / Gradle / Ivy

/*
 * Copyright (C) 2018  Sun.Hao
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

package lodsve.mybatis.utils;

import lodsve.mybatis.repository.bean.EntityTable;
import lodsve.mybatis.repository.bean.VersionColumn;
import org.apache.commons.collections.MapUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceUtils;

import javax.persistence.NoResultException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 乐观锁插件工具类.
 *
 * @author sunhao([email protected])
 */
public class VersionUtils {
    private static final Logger logger = LoggerFactory.getLogger(VersionUtils.class);
    private static final String VERSION_SQL = "SELECT %s FROM %s WHERE %s";

    /**
     * 获取当前版本号
     *
     * @param mappedStatement mappedStatement
     * @param table           表对象
     * @param keyMap          查询条件组合(property name in domain object -> value)
     * @param              版本号的类型
     * @return 当前版本号
     * @throws SQLException sql执行异常
     */
    @SuppressWarnings("unchecked")
    public static  T getCurrentVersion(MappedStatement mappedStatement, EntityTable table, Map keyMap) throws SQLException {
        if (MapUtils.isEmpty(keyMap)) {
            return null;
        }

        VersionColumn version = table.getVersionColumn();
        String whereSql = keyMap.keySet().stream().map(key -> SqlUtils.camelHumpToUnderline(key).toUpperCase() + " = ?").collect(Collectors.joining(" AND "));

        String versionSql = String.format(VERSION_SQL, version.getColumn(), table.getName(), whereSql);

        ResultSet rs = null;
        Configuration configuration = mappedStatement.getConfiguration();

        Connection connection = DataSourceUtils.getConnection(configuration.getEnvironment().getDataSource());
        try (PreparedStatement versionStmt = connection.prepareStatement(versionSql)) {
            AtomicInteger i = new AtomicInteger();
            keyMap.forEach((key, value) -> {
                ParameterMapping parameterMapping = new ParameterMapping.Builder(configuration, key, value.getClass()).build();
                TypeHandler typeHandler = parameterMapping.getTypeHandler();
                try {
                    typeHandler.setParameter(versionStmt, i.get() + 1, value, parameterMapping.getJdbcType());
                    i.getAndIncrement();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            });

            rs = versionStmt.executeQuery();
            Object currentVersion = null;
            if (rs.next()) {
                // 为了解决使用阿里Druid数据源时,getObject(int columnIndex, Class type)会直接抛SQLFeatureNotSupportedException这个异常的问题
                // 已经在GitHub上提了issue,不知道有没有回复 https://github.com/alibaba/druid/issues/2867
                currentVersion = rs.getObject(1, Collections.singletonMap(version.getColumn(), version.getJavaType()));
            }

            if (null == currentVersion) {
                throw new NoResultException(String.format("Can't find a record for '%s' in table '%s'!", keyMap.keySet().stream().map(k -> SqlUtils.camelHumpToUnderline(k).toUpperCase() + " = " + keyMap.get(k)).collect(Collectors.joining(",")), table.getName()));
            }

            return (T) currentVersion;
        } catch (SQLException e) {
            logger.error("查询当前version出错", e);
            throw e;
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    logger.error("exception happens when doing: ResultSet.close()", e);
                }
            }
            DataSourceUtils.releaseConnection(connection, configuration.getEnvironment().getDataSource());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy