hibernate 自定義表名與列名 - 增刪改查分頁 - 相容Mysql和Oracle

人间春风意發表於2024-09-27

1. 新增service,先組裝SQL

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class DataService {

    @Autowired
    private CustomRepository customRepository;

    @Autowired
    private EventService EventService;

    @Value("${spring.jpa.database}")
    private String database;

    public ApiResult addCustomData(CustomDataDTO customDataDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<CustomColumnData> dataList = customDataDTO.getDatas();
        StringBuilder sql = new StringBuilder();
        StringBuilder strColumns = new StringBuilder();
        StringBuilder strValues = new StringBuilder();
        for (int i =0; i < dataList.size(); i++) {
            CustomColumnData data = dataList.get(i);
            strColumns.append("`").append(data.getColumnName()).append("`")
                    .append((i<dataList.size() - 1) ? "," : "");
            strValues.append("'").append(data.getColumnValue()).append("'")
                    .append((i<dataList.size() - 1) ? "," : "");
        }
        sql.append(" insert into ").append(cusTableName).append(" (").append(strColumns).append(") values ").append("(").append(strValues).append(")");
        int res = customRepository.insertData(sql.toString());
        return ApiResult.ok(res);
    }

    public ApiResult addCustomDataAutoID(CustomDataDTO customDataDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<CustomColumnData> dataList = customDataDTO.getDatas();
        StringBuilder strColumns = new StringBuilder();
        StringBuilder strValues = new StringBuilder();
        for (int i =0; i < dataList.size(); i++) {
            CustomColumnData data = dataList.get(i);
            strColumns.append(data.getColumnName())
                    .append((i<dataList.size() - 1) ? "," : "");
            strValues.append("'").append(data.getColumnValue()).append("'")
                    .append((i<dataList.size() - 1) ? "," : "");
        }

        int res = customRepository.insertDataAutoID(cusTableName, strColumns.toString(), strValues.toString());
        return ApiResult.ok(res);
    }

    public ApiResult updateCustomData(CustomDataDTO customDataDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<CustomColumnData> dataList = customDataDTO.getDatas();
        StringBuilder setValues = new StringBuilder();
        for (int i =0; i < dataList.size(); i++) {
            CustomColumnData data = dataList.get(i);
            if (data.getColumnName() != null && !data.getColumnName().isEmpty()) {
                setValues.append(data.getColumnName())
                        .append("=").append("'").append(data.getColumnValue()).append("'")
                        .append((i<dataList.size() - 1) ? "," : "");
            }
        }

        int res = customRepository.updateDataSetByID(cusTableName , String.valueOf(setValues), customDataDTO.getDataId());
        return ApiResult.ok(res);
    }

    public ApiResult deleteCustomDataByID(CustomDataCondition customDataCondition) {
        String cusTableName = customDataDTO.getTargetTable();
        StringBuilder setValues = new StringBuilder();
        List<Long> longList = customDataCondition.getIdList();
        for (int i =0; i < longList.size(); i++) {
            long id = longList.get(i);
            if (id > 0) {
                setValues.append(id)
                        .append((i<longList.size() - 1) ? "," : "");
            }
        }
        int res = customRepository.deleteDataSetByID(cusTableName, setValues.toString());
        return ApiResult.ok(res);
    }


    public ApiResult getAll(CustomDataQueryDTO customDataDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<CustomColumnQueryData> dataList = customDataDTO.getDatas();
        StringBuilder setValues = new StringBuilder();
        for (int i =0; i < dataList.size(); i++) {
            CustomColumnQueryData data = dataList.get(i);
            if (data.getColumnName() != null && !data.getColumnName().isEmpty()) {
                setValues.append(data.getColumnName());
                if (data.isLike()) {
                    setValues.append(" like '%").append(data.getColumnValue()).append("%'");
                } else {
                    setValues.append("=").append("'").append(data.getColumnValue()).append("'");
                }
                setValues.append((i<dataList.size() - 1) ? "," : "");
            }
        }
        List res = customRepository.queryAllDataByTableName(cusTableName , String.valueOf(setValues));
        return ApiResult.ok(res);
    }



    public ApiResult getPage(CustomDataQueryDTO customDataQueryDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<CustomColumnQueryData> dataList = customDataQueryDTO.getDatas();
        StringBuilder setValues = new StringBuilder();
        for (int i =0; i < dataList.size(); i++) {
            CustomColumnQueryData data = dataList.get(i);
            if (data.getColumnName() != null && !data.getColumnName().isEmpty()) {
                setValues.append(data.getColumnName());
                if (data.isLike()) {
                    setValues.append(" like '%").append(data.getColumnValue()).append("%'");
                } else {
                    setValues.append("=").append("'").append(data.getColumnValue()).append("'");
                }
                setValues.append((i < dataList.size() - 1) ? "," : "");
            }
        }
        Page res = customRepository.queryPageDataByTableName(cusTableName , String.valueOf(setValues),  customDataQueryDTO.getSize(), customDataQueryDTO.getPage());
        return ApiResult.ok(res);
    }


    public ApiResult queryColumnNamesByTableName(CustomDataQueryDTO customDataQueryDTO) {
        String cusTableName = customDataDTO.getTargetTable();
        List<String> names;
        if (database.equals("MYSQL")) {
            names = customRepository.queryColumnNamesByTableNameMySQL(cusTableName);
        } else {
            names = customRepository.queryColumnNamesByTableNameOracle(cusTableName);
        }
        return ApiResult.ok(names);
    }

}

2. 新增Repository

import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Repository
public class CustomRepository {


    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    @Modifying
    @Query
    public int insertData(String sql) {
        log.info(" 請求的SQL: \n" + sql);
        return entityManager.createNativeQuery(sql).executeUpdate();
    }

    @Transactional
    @Modifying
    @Query
    public int insertDataAutoID(String cusTableName, String strColumns, String strValues) {
        StringBuilder sql = new StringBuilder();
        sql.append(" insert into ").append(cusTableName).append(" ( ").append(strColumns).append(") values ").append("( ").append(strValues).append(")");
        log.info(" 請求的SQL: " + sql);
        return entityManager.createNativeQuery(sql.toString()).executeUpdate();
    }

    @Transactional
    @Modifying
    @Query
    public int updateDataSetByID(String cusTableName, String setValues, long id) {
        StringBuilder sql = new StringBuilder();
        sql.append(" update ").append(cusTableName).append(" set ").append(setValues).append(" where ").append("( id = ").append(id).append(")");
        log.info(" 執行的SQL: " + sql);
        return entityManager.createNativeQuery(sql.toString()).executeUpdate();
    }

    @Transactional
    @Modifying
    @Query
    public int deleteDataSetByID(String cusTableName, String idSqlStr) {
        StringBuilder sql = new StringBuilder();
        sql.append(" delete from  ").append(cusTableName).append(" where   id in ( ").append(idSqlStr).append(")");
        log.info(" 執行的SQL: " + sql);
        return entityManager.createNativeQuery(sql.toString()).executeUpdate();
    }

    @Modifying
    @Query
    public List queryAllDataByTableName(String cusTableName, String whereCondition) {
        StringBuilder sql = new StringBuilder();
        sql.append(" select * from ").append(cusTableName);
        if (!whereCondition.isEmpty()) {
            sql.append(" where ").append(whereCondition);
        }
        javax.persistence.Query query = entityManager.createNativeQuery(sql.toString());
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        log.info(" 執行的SQL: " + sql);
        return query.getResultList();
    }


    @Modifying
    @Query
    public Page queryPageDataByTableName(String cusTableName, String whereCondition, int size, int page) {
        StringBuilder countSql = new StringBuilder();
        countSql.append("select count(*) from ").append(cusTableName).append(" e ");
        if (!whereCondition.isEmpty()) {
            countSql.append(" where ").append(whereCondition);
        }
        StringBuilder sql = new StringBuilder();
        sql.append("select * from ").append(cusTableName);
        if (!whereCondition.isEmpty()) {
            sql.append(" where ").append(whereCondition);
        }
        log.info(" 執行的SQL: " + sql);
        Pageable pageable = PageRequest.of(page, size);
        return findWithPagination(pageable, sql.toString(), countSql.toString());
    }

    public Page findWithPagination(Pageable pageable, String sql, String countSql) {
        String countQuery = countSql;
        javax.persistence.Query cntQuery = entityManager.createNativeQuery(countQuery);
        BigInteger cnt = BigInteger.valueOf(0);
        Object countObj = cntQuery.getSingleResult();
        if (countObj instanceof BigDecimal) {
            cnt = BigInteger.valueOf(Integer.parseInt(String.valueOf(countObj)));
        } else {
            cnt = (BigInteger) cntQuery.getSingleResult();
        }
        javax.persistence.Query query = entityManager.createNativeQuery(sql);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        query.setFirstResult((int) pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());
        List list = query.getResultList();
        Page pageResult = new PageImpl<>(list, pageable, cnt.longValue());
        // 建立並返回一個Page物件
        return pageResult;
    }


    /**
     * 獲取指定表的所有欄位名稱 MysqlDB
     * @param cusTableName 表名
     * @return 欄位列名稱
     */
    @Modifying
    @Query
    public List<String> queryColumnNamesByTableNameMySQL(String cusTableName) {
        StringBuilder sql = new StringBuilder();
        // oracle寫法
        sql.append(" SHOW COLUMNS FROM ").append(cusTableName).append("");
        javax.persistence.Query query = entityManager.createNativeQuery(sql.toString());
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        log.info(" 執行的SQL: " + sql);
        List<String> columns = new ArrayList<>();
        List<HashMap> resultList = query.getResultList();
        for (HashMap map : resultList) {
            String column =  map.get("Field").toString();
            columns.add(column);
        }
        log.info("所有的列名: " + columns);
        return columns;
    }


    /**
     * 獲取指定表的所有欄位名稱 OracleDB
     * @param cusTableName 表名
     * @return 欄位列名稱
     */
    @Modifying
    @Query
    public List<String> queryColumnNamesByTableNameOracle(String cusTableName) {
        StringBuilder sql = new StringBuilder();
        // oracle寫法
        sql.append(" SELECT  COLUMN_NAME FROM user_tab_columns  where TABLE_NAME = '").append(cusTableName).append("'");
        javax.persistence.Query query = entityManager.createNativeQuery(sql.toString());
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        log.info(" 執行的SQL: " + sql);
        List<String> columns = new ArrayList<>();
        List<HashMap> resultList = query.getResultList();
        for (HashMap map : resultList) {
            String column =  map.get("COLUMN_NAME").toString();
            columns.add(column);
        }
        log.info("所有的列名: " + columns);
        return columns;
    }
}

3. 使用的Bean

@Data
@ApiModel("動態查詢")
public class CustomDataQueryDTO {

    @ApiModelProperty(value = "目的表")
    private String targetTable;
    @ApiModelProperty(value = "每頁顯示多少資料")
    private int size;
    @ApiModelProperty(value = "查詢第幾頁")
    private int page;
    @ApiModelProperty(value = "列名與Value值的集合")
    private List<CustomColumnQueryData> datas;

}


@Data
@ApiModel("列名與Value值的集合")
public class CustomColumnQueryData {
    @ApiModelProperty(value = "所需操作的欄位")
    private String columnName;
    @ApiModelProperty(value = "欄位對應的Value")
    private String columnValue;
    @ApiModelProperty(value = "是否是模糊查詢,true為模糊查詢,false為相等查詢")
    private boolean like;
}



@Data
@ApiModel("資料新增/更新")
public class CustomDataCondition {

    @ApiModelProperty(value = "目的表")
    private String targetTable;

    @ApiModelProperty(value = "刪除/編輯的目的表裡的資料ID集合")
    private List<Long> idList;

    @ApiModelProperty(value = "新增/編輯時列名與Value值的集合")
    private List<CustomColumnData> datas;

}

@Data
@ApiModel("列名與Value值的集合")
public class CustomColumnData {
    @ApiModelProperty(value = "目標欄位")
    private String columnName;
    @ApiModelProperty(value = "目標值")
    private String columnValue;
}

相關文章