fix: 1、增加行业基础数据表;2、调整所有行业指数数据关联的外键;3、导入每日个股交易数据时,检查个股基础数据和行业数据,并进行导入和更新

dev_refactor_0120_qoder
Lxy 4 months ago
parent 7bf874398a
commit d6ad9c4838

@ -0,0 +1,130 @@
package com.ruoyi.newstocksystem.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.Date;
/**
*
* t_industry_basic
*
* @author lxy
* @date 2026-01-23
*/
public class TIndustryBasic extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 行业代码如802089.EI */
@Excel(name = "行业代码")
private String industryCode;
/** 行业名称(如"银行" */
@Excel(name = "行业名称")
private String industryName;
/** 行业级别1=一级行业2=二级行业3=三级行业等) */
@Excel(name = "行业级别")
private Integer industryLevel;
/** 父级行业代码 */
@Excel(name = "父级行业代码")
private String parentIndustryCode;
/** 行业描述 */
@Excel(name = "行业描述")
private String description;
/** 状态1=正常0=禁用) */
@Excel(name = "状态", readConverterExp = "1=正常,0=禁用")
private Integer status;
/** 排序 */
@Excel(name = "排序")
private Integer sortOrder;
public String getIndustryCode()
{
return industryCode;
}
public void setIndustryCode(String industryCode)
{
this.industryCode = industryCode;
}
public String getIndustryName()
{
return industryName;
}
public void setIndustryName(String industryName)
{
this.industryName = industryName;
}
public Integer getIndustryLevel()
{
return industryLevel;
}
public void setIndustryLevel(Integer industryLevel)
{
this.industryLevel = industryLevel;
}
public String getParentIndustryCode()
{
return parentIndustryCode;
}
public void setParentIndustryCode(String parentIndustryCode)
{
this.parentIndustryCode = parentIndustryCode;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Integer getStatus()
{
return status;
}
public void setStatus(Integer status)
{
this.status = status;
}
public Integer getSortOrder()
{
return sortOrder;
}
public void setSortOrder(Integer sortOrder)
{
this.sortOrder = sortOrder;
}
@Override
public String toString()
{
return "TIndustryBasic{" +
"industryCode='" + industryCode + '\'' +
", industryName='" + industryName + '\'' +
", industryLevel=" + industryLevel +
", parentIndustryCode='" + parentIndustryCode + '\'' +
", description='" + description + '\'' +
", status=" + status +
", sortOrder=" + sortOrder +
'}';
}
}

@ -80,14 +80,34 @@ public class TStockDailyTrade extends BaseEntity
private BigDecimal momentum60d;
/** 证券名称(查询时关联获取) */
@Excel(name = "证券名称")
private String stockName;
/** 行业指数代码(查询时关联获取) */
@Excel(name = "所属东财行业指数代码\n[行业类别]2级")
private String industryIndexCode;
/** 行业指数名称(查询时关联获取) */
@Excel(name = "所属东财行业指数2级")
private String industryIndexName;
/** 首发上市日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "首发上市日期", dateFormat = "yyyy-MM-dd")
private Date listingDate;
/** 上市天数(冗余存储,提升查询效率) */
@Excel(name = "上市天数")
private Integer listingDays;
/** 是否为ST股票1=是0=否) */
@Excel(name = "是否ST", readConverterExp = "1=是,0=否")
private Integer isSt;
/** 是否为*ST股票1=是0=否) */
@Excel(name = "是否*ST", readConverterExp = "1=是,0=否")
private Integer isStarSt;
public String getStockCode()
{
return stockCode;
@ -268,6 +288,46 @@ public class TStockDailyTrade extends BaseEntity
this.industryIndexName = industryIndexName;
}
public Date getListingDate()
{
return listingDate;
}
public void setListingDate(Date listingDate)
{
this.listingDate = listingDate;
}
public Integer getListingDays()
{
return listingDays;
}
public void setListingDays(Integer listingDays)
{
this.listingDays = listingDays;
}
public Integer getIsSt()
{
return isSt;
}
public void setIsSt(Integer isSt)
{
this.isSt = isSt;
}
public Integer getIsStarSt()
{
return isStarSt;
}
public void setIsStarSt(Integer isStarSt)
{
this.isStarSt = isStarSt;
}
@Override
public String toString()
{
@ -287,6 +347,13 @@ public class TStockDailyTrade extends BaseEntity
", momentum10d=" + momentum10d +
", momentum20d=" + momentum20d +
", momentum60d=" + momentum60d +
", stockName='" + stockName + '\'' +
", industryIndexCode='" + industryIndexCode + '\'' +
", industryIndexName='" + industryIndexName + '\'' +
", listingDate=" + listingDate +
", listingDays=" + listingDays +
", isSt=" + isSt +
", isStarSt=" + isStarSt +
'}';
}
}

@ -0,0 +1,69 @@
package com.ruoyi.newstocksystem.mapper;
import java.util.List;
import com.ruoyi.newstocksystem.domain.TIndustryBasic;
/**
* Mapper
*
* @author lxy
* @date 2026-01-23
*/
public interface TIndustryBasicMapper
{
/**
*
*
* @param industryCode
* @return
*/
public TIndustryBasic selectTIndustryBasicByCode(String industryCode);
/**
*
*
* @param industryBasic
* @return
*/
public List<TIndustryBasic> selectTIndustryBasicList(TIndustryBasic industryBasic);
/**
*
*
* @param industryBasic
* @return
*/
public int insertTIndustryBasic(TIndustryBasic industryBasic);
/**
*
*
* @param industryBasic
* @return
*/
public int updateTIndustryBasic(TIndustryBasic industryBasic);
/**
*
*
* @param industryCode
* @return
*/
public int deleteTIndustryBasicByCode(String industryCode);
/**
*
*
* @param industryCodes
* @return
*/
public int deleteTIndustryBasicByCodes(String[] industryCodes);
/**
* Upsert
*
* @param industryBasicList
* @return
*/
public int batchUpsertIndustryBasic(List<TIndustryBasic> industryBasicList);
}

@ -77,4 +77,21 @@ public interface IIndustryIndexService
* @return
*/
public List<String> selectTradeDates();
}
/**
*
*
* @param industryCode
* @return truefalse
*/
public boolean checkIndustryBasicExists(String industryCode);
/**
*
*
* @param industryCode
* @param industryName
* @return
*/
public int createIndustryBasic(String industryCode, String industryName);
}

@ -0,0 +1,61 @@
package com.ruoyi.newstocksystem.service;
import java.util.List;
import com.ruoyi.newstocksystem.domain.TIndustryBasic;
/**
* Service
*
* @author lxy
* @date 2026-01-23
*/
public interface ITIndustryBasicService
{
/**
*
*
* @param industryCode
* @return
*/
public TIndustryBasic selectTIndustryBasicByCode(String industryCode);
/**
*
*
* @param industryBasic
* @return
*/
public List<TIndustryBasic> selectTIndustryBasicList(TIndustryBasic industryBasic);
/**
*
*
* @param industryBasic
* @return
*/
public int insertTIndustryBasic(TIndustryBasic industryBasic);
/**
*
*
* @param industryBasic
* @return
*/
public int updateTIndustryBasic(TIndustryBasic industryBasic);
/**
*
*
* @param industryCodes
* @return
*/
public int deleteTIndustryBasicByCodes(String[] industryCodes);
/**
*
*
* @param industryBasicList
* @return
*/
public int importIndustryBasic(List<TIndustryBasic> industryBasicList);
}

@ -3,16 +3,15 @@ package com.ruoyi.newstocksystem.service.impl;
import java.util.Date;
import java.util.List;
import com.ruoyi.newstocksystem.mapper.TIndustryIndexMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.newstocksystem.domain.TIndustryIndex;
import com.ruoyi.newstocksystem.mapper.TIndustryIndexMapper;
import com.ruoyi.newstocksystem.service.IIndustryIndexService;
import com.ruoyi.newstocksystem.service.ITIndustryBasicService;
/**
* Service
* Service
*
* @author lxy
* @date 2026-01-21
@ -22,6 +21,9 @@ public class IndustryIndexServiceImpl implements IIndustryIndexService
{
@Autowired
private TIndustryIndexMapper industryIndexMapper;
@Autowired
private ITIndustryBasicService industryBasicService;
@Override
public TIndustryIndex selectIndustryIndexByCodeAndDate(String industryIndexCode, Date tradeDate)
@ -60,35 +62,9 @@ public class IndustryIndexServiceImpl implements IIndustryIndexService
}
@Override
@Transactional
public int importIndustryIndex(List<TIndustryIndex> industryIndexList, Date tradeDate)
{
if (industryIndexList == null || industryIndexList.isEmpty())
{
return 0;
}
// 设置交易日期
for (TIndustryIndex industryIndex : industryIndexList)
{
if (industryIndex.getTradeDate() == null)
{
industryIndex.setTradeDate(tradeDate);
}
}
int count = 0;
int batchSize = 500;
// 分批导入数据
for (int i = 0; i < industryIndexList.size(); i += batchSize)
{
int end = Math.min(i + batchSize, industryIndexList.size());
List<TIndustryIndex> batchList = industryIndexList.subList(i, end);
count += industryIndexMapper.batchUpsertIndustryIndex(batchList);
}
return count;
return industryIndexMapper.batchUpsertIndustryIndex(industryIndexList);
}
@Override
@ -96,4 +72,25 @@ public class IndustryIndexServiceImpl implements IIndustryIndexService
{
return industryIndexMapper.selectTradeDates();
}
}
@Override
public boolean checkIndustryBasicExists(String industryCode)
{
// 检查行业基础数据是否存在
return industryBasicService.selectTIndustryBasicByCode(industryCode) != null;
}
@Override
public int createIndustryBasic(String industryCode, String industryName)
{
// 创建行业基础数据
com.ruoyi.newstocksystem.domain.TIndustryBasic industryBasic = new com.ruoyi.newstocksystem.domain.TIndustryBasic();
industryBasic.setIndustryCode(industryCode);
industryBasic.setIndustryName(industryName);
industryBasic.setIndustryLevel(2); // 默认为二级行业
industryBasic.setStatus(1); // 默认启用
industryBasic.setSortOrder(0); // 默认排序
return industryBasicService.insertTIndustryBasic(industryBasic);
}
}

@ -2,14 +2,27 @@ package com.ruoyi.newstocksystem.service.impl;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.newstocksystem.domain.TIndustryBasic;
import com.ruoyi.newstocksystem.domain.TStockBasic;
import com.ruoyi.newstocksystem.domain.TStockDailyTrade;
import com.ruoyi.newstocksystem.mapper.TStockBasicMapper;
import com.ruoyi.newstocksystem.mapper.TStockDailyTradeMapper;
import com.ruoyi.newstocksystem.service.IIndustryIndexService;
import com.ruoyi.newstocksystem.service.IStockBasicService;
import com.ruoyi.newstocksystem.service.IStockDailyTradeService;
import com.ruoyi.newstocksystem.service.ITIndustryBasicService;
/**
* Service
@ -20,9 +33,20 @@ import com.ruoyi.newstocksystem.service.IStockDailyTradeService;
@Service
public class StockDailyTradeServiceImpl implements IStockDailyTradeService
{
private static final Logger logger = LoggerFactory.getLogger(StockDailyTradeServiceImpl.class);
@Autowired
private TStockDailyTradeMapper stockDailyTradeMapper;
@Autowired
private IStockBasicService stockBasicService;
@Autowired
private IIndustryIndexService industryIndexService;
@Autowired
private ITIndustryBasicService industryBasicService;
@Override
public TStockDailyTrade selectStockDailyTradeByCodeAndDate(String stockCode, Date tradeDate)
{
@ -86,17 +110,255 @@ public class StockDailyTradeServiceImpl implements IStockDailyTradeService
}
}
long startTime = System.currentTimeMillis();
logger.info("开始处理股票基础数据,待处理记录数: {}", stockDailyTradeList.size());
// 收集所有需要检查的行业代码
Set<String> industryCodes = new HashSet<>();
for (TStockDailyTrade stockDailyTrade : stockDailyTradeList)
{
if (stockDailyTrade.getIndustryIndexCode() != null && !stockDailyTrade.getIndustryIndexCode().trim().isEmpty())
{
industryCodes.add(stockDailyTrade.getIndustryIndexCode());
}
}
// 检查并确保行业基础数据存在
logger.info("开始检查行业基础数据,需要检查的行业代码数量: {}", industryCodes.size());
if (!industryCodes.isEmpty())
{
// 检查每个行业代码是否存在,如果不存在则创建
for (String industryCode : industryCodes)
{
if (!industryIndexService.checkIndustryBasicExists(industryCode))
{
// 如果行业基础数据不存在,创建一个基础记录
String industryName = industryCode; // 使用代码作为默认名称
if (stockDailyTradeList != null) {
// 尝试从数据中获取行业名称
for (TStockDailyTrade trade : stockDailyTradeList) {
if (trade.getIndustryIndexCode() != null && trade.getIndustryIndexCode().equals(industryCode)) {
if (trade.getIndustryIndexName() != null) {
industryName = trade.getIndustryIndexName();
break;
}
}
}
}
industryIndexService.createIndustryBasic(industryCode, industryName);
}
}
}
// 收集所有需要检查的股票代码
Set<String> stockCodes = new HashSet<>();
for (TStockDailyTrade stockDailyTrade : stockDailyTradeList)
{
stockCodes.add(stockDailyTrade.getStockCode());
}
// 一次性读取所有存在的股票基础数据
logger.info("开始批量读取股票基础数据,股票代码数量: {}", stockCodes.size());
long loadStart = System.currentTimeMillis();
List<TStockBasic> existingBasics = stockBasicService.selectStockBasicList(new TStockBasic());
// 将现有基础数据转换为Map以便快速查找
Map<String, TStockBasic> existingBasicsMap = new HashMap<>();
for (TStockBasic basic : existingBasics)
{
if (stockCodes.contains(basic.getStockCode()))
{
existingBasicsMap.put(basic.getStockCode(), basic);
}
}
long loadEnd = System.currentTimeMillis();
logger.info("股票基础数据读取完成,耗时: {} ms", (loadEnd - loadStart));
// 准备需要插入和更新的数据
List<TStockBasic> newBasicsToInsert = new ArrayList<>();
List<TStockBasic> basicsToUpdate = new ArrayList<>();
logger.info("开始比较和分类股票基础数据");
long compareStart = System.currentTimeMillis();
for (TStockDailyTrade stockDailyTrade : stockDailyTradeList)
{
TStockBasic existingBasic = existingBasicsMap.get(stockDailyTrade.getStockCode());
if (existingBasic == null)
{
// 如果不存在,创建新的股票基础数据记录
// 只有当必要字段不为空时才插入
if (stockDailyTrade.getStockCode() != null && stockDailyTrade.getStockName() != null)
{
TStockBasic newBasic = new TStockBasic();
newBasic.setStockCode(stockDailyTrade.getStockCode());
newBasic.setStockName(stockDailyTrade.getStockName());
// 设置从TStockDailyTrade传入的其他基础信息
if (stockDailyTrade.getIndustryIndexCode() != null && !stockDailyTrade.getIndustryIndexCode().trim().isEmpty()) {
newBasic.setIndustryIndexCode(stockDailyTrade.getIndustryIndexCode());
} else {
newBasic.setIndustryIndexCode(""); // 设置默认值
}
if (stockDailyTrade.getIndustryIndexName() != null) {
newBasic.setIndustryIndexName(stockDailyTrade.getIndustryIndexName());
} else {
newBasic.setIndustryIndexName("");
}
if (stockDailyTrade.getListingDate() != null) {
newBasic.setListingDate(stockDailyTrade.getListingDate());
}
if (stockDailyTrade.getListingDays() != null) {
newBasic.setListingDays(stockDailyTrade.getListingDays());
}
// 确保ST相关字段有默认值
if (stockDailyTrade.getIsSt() != null) {
newBasic.setIsSt(stockDailyTrade.getIsSt());
} else {
newBasic.setIsSt(0); // 默认不是ST股票
}
if (stockDailyTrade.getIsStarSt() != null) {
newBasic.setIsStarSt(stockDailyTrade.getIsStarSt());
} else {
newBasic.setIsStarSt(0); // 默认不是*ST股票
}
newBasicsToInsert.add(newBasic);
}
}
else
{
// 如果存在,检查各字段是否发生变化,如有变化则更新
boolean needUpdate = false;
// 只有当新值不为null时才更新
if (stockDailyTrade.getStockName() != null &&
(existingBasic.getStockName() == null || !existingBasic.getStockName().equals(stockDailyTrade.getStockName())))
{
existingBasic.setStockName(stockDailyTrade.getStockName());
needUpdate = true;
}
if (stockDailyTrade.getIndustryIndexCode() != null &&
(existingBasic.getIndustryIndexCode() == null || !existingBasic.getIndustryIndexCode().equals(stockDailyTrade.getIndustryIndexCode())))
{
existingBasic.setIndustryIndexCode(stockDailyTrade.getIndustryIndexCode());
needUpdate = true;
}
if (stockDailyTrade.getIndustryIndexName() != null &&
(existingBasic.getIndustryIndexName() == null || !existingBasic.getIndustryIndexName().equals(stockDailyTrade.getIndustryIndexName())))
{
existingBasic.setIndustryIndexName(stockDailyTrade.getIndustryIndexName());
needUpdate = true;
}
if (stockDailyTrade.getListingDate() != null &&
(existingBasic.getListingDate() == null || !existingBasic.getListingDate().equals(stockDailyTrade.getListingDate())))
{
existingBasic.setListingDate(stockDailyTrade.getListingDate());
needUpdate = true;
}
if (stockDailyTrade.getListingDays() != null &&
(existingBasic.getListingDays() == null || !existingBasic.getListingDays().equals(stockDailyTrade.getListingDays())))
{
existingBasic.setListingDays(stockDailyTrade.getListingDays());
needUpdate = true;
}
if (stockDailyTrade.getIsSt() != null &&
(existingBasic.getIsSt() == null || !existingBasic.getIsSt().equals(stockDailyTrade.getIsSt())))
{
existingBasic.setIsSt(stockDailyTrade.getIsSt());
needUpdate = true;
}
if (stockDailyTrade.getIsStarSt() != null &&
(existingBasic.getIsStarSt() == null || !existingBasic.getIsStarSt().equals(stockDailyTrade.getIsStarSt())))
{
existingBasic.setIsStarSt(stockDailyTrade.getIsStarSt());
needUpdate = true;
}
if (needUpdate)
{
// 确保ST相关字段始终有值避免数据库约束错误
if (existingBasic.getIsSt() == null) {
existingBasic.setIsSt(0);
}
if (existingBasic.getIsStarSt() == null) {
existingBasic.setIsStarSt(0);
}
basicsToUpdate.add(existingBasic);
}
}
}
long compareEnd = System.currentTimeMillis();
logger.info("股票基础数据比较完成,耗时: {} ms", (compareEnd - compareStart));
// 批量插入新的股票基础数据
if (!newBasicsToInsert.isEmpty())
{
logger.info("准备批量插入 {} 条新的股票基础数据", newBasicsToInsert.size());
long insertStart = System.currentTimeMillis();
stockBasicService.importStockBasic(newBasicsToInsert); // 使用importStockBasic方法进行批量插入
long insertEnd = System.currentTimeMillis();
logger.info("股票基础数据插入完成,耗时: {} ms", (insertEnd - insertStart));
}
else
{
logger.info("无需插入新的股票基础数据");
}
// 批量更新股票基础数据
if (!basicsToUpdate.isEmpty())
{
logger.info("准备批量更新 {} 条股票基础数据", basicsToUpdate.size());
long updateStart = System.currentTimeMillis();
for (TStockBasic basic : basicsToUpdate)
{
// 确保ST相关字段始终有值避免数据库约束错误
if (basic.getIsSt() == null) {
basic.setIsSt(0);
}
if (basic.getIsStarSt() == null) {
basic.setIsStarSt(0);
}
stockBasicService.updateStockBasic(basic);
}
long updateEnd = System.currentTimeMillis();
logger.info("股票基础数据更新完成,耗时: {} ms", (updateEnd - updateStart));
}
else
{
logger.info("无需更新股票基础数据");
}
long checkTime = System.currentTimeMillis();
logger.info("股票基础数据处理完成,耗时: {} ms", (checkTime - startTime));
// 批量插入每日交易数据
int count = 0;
int batchSize = 500;
// 分批导入数据
logger.info("开始批量插入每日交易数据,总记录数: {}", stockDailyTradeList.size());
long tradeDataStartTime = System.currentTimeMillis();
for (int i = 0; i < stockDailyTradeList.size(); i += batchSize)
{
int end = Math.min(i + batchSize, stockDailyTradeList.size());
List<TStockDailyTrade> batchList = stockDailyTradeList.subList(i, end);
count += stockDailyTradeMapper.batchUpsertStockDailyTrade(batchList);
int batchCount = stockDailyTradeMapper.batchUpsertStockDailyTrade(batchList);
count += batchCount;
logger.info("批次 [{}-{}] 交易数据插入完成,本次插入: {} 条", i, end, batchCount);
}
long tradeDataEndTime = System.currentTimeMillis();
logger.info("每日交易数据批量插入完成,总插入: {} 条,耗时: {} ms", count, (tradeDataEndTime - tradeDataStartTime));
long totalTime = System.currentTimeMillis() - startTime;
logger.info("导入任务完成,总耗时: {} ms", totalTime);
return count;
}
@ -117,4 +379,4 @@ public class StockDailyTradeServiceImpl implements IStockDailyTradeService
{
return stockDailyTradeMapper.selectStrongStockList(stockDailyTrade);
}
}
}

@ -2,14 +2,26 @@ package com.ruoyi.newstocksystem.service.impl;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.newstocksystem.domain.TIndustryBasic;
import com.ruoyi.newstocksystem.domain.TStockBasic;
import com.ruoyi.newstocksystem.domain.TStockHighLowStatus;
import com.ruoyi.newstocksystem.mapper.TStockHighLowStatusMapper;
import com.ruoyi.newstocksystem.service.IIndustryIndexService;
import com.ruoyi.newstocksystem.service.IStockBasicService;
import com.ruoyi.newstocksystem.service.IStockHighLowStatusService;
import com.ruoyi.newstocksystem.service.ITIndustryBasicService;
/**
* Service
@ -20,9 +32,20 @@ import com.ruoyi.newstocksystem.service.IStockHighLowStatusService;
@Service
public class StockHighLowStatusServiceImpl implements IStockHighLowStatusService
{
private static final Logger logger = LoggerFactory.getLogger(StockHighLowStatusServiceImpl.class);
@Autowired
private TStockHighLowStatusMapper stockHighLowStatusMapper;
@Autowired
private IStockBasicService stockBasicService;
@Autowired
private IIndustryIndexService industryIndexService;
@Autowired
private ITIndustryBasicService industryBasicService;
@Override
public TStockHighLowStatus selectStockHighLowStatusByCodeAndDate(String stockCode, Date tradeDate)
{
@ -86,17 +109,158 @@ public class StockHighLowStatusServiceImpl implements IStockHighLowStatusService
}
}
long startTime = System.currentTimeMillis();
logger.info("开始处理股票基础数据,待处理记录数: {}", stockHighLowStatusList.size());
// 收集所有需要检查的行业代码
Set<String> industryCodes = new HashSet<>();
for (TStockHighLowStatus stockHighLowStatus : stockHighLowStatusList)
{
if (stockHighLowStatus.getIndustryIndexCode() != null && !stockHighLowStatus.getIndustryIndexCode().trim().isEmpty())
{
industryCodes.add(stockHighLowStatus.getIndustryIndexCode());
}
}
// 检查并确保行业基础数据存在
logger.info("开始检查行业基础数据,需要检查的行业代码数量: {}", industryCodes.size());
if (!industryCodes.isEmpty())
{
// 检查每个行业代码是否存在,如果不存在则创建
for (String industryCode : industryCodes)
{
if (!industryIndexService.checkIndustryBasicExists(industryCode))
{
// 如果行业基础数据不存在,创建一个基础记录
String industryName = industryCode; // 使用代码作为默认名称
if (stockHighLowStatusList != null) {
// 尝试从数据中获取行业名称
for (TStockHighLowStatus status : stockHighLowStatusList) {
if (status.getIndustryIndexCode() != null && status.getIndustryIndexCode().equals(industryCode)) {
if (status.getIndustryIndexName() != null) {
industryName = status.getIndustryIndexName();
break;
}
}
}
}
industryIndexService.createIndustryBasic(industryCode, industryName);
}
}
}
// 收集所有需要检查的股票代码
Set<String> stockCodes = new HashSet<>();
for (TStockHighLowStatus stockHighLowStatus : stockHighLowStatusList)
{
stockCodes.add(stockHighLowStatus.getStockCode());
}
// 一次性读取所有存在的股票基础数据
logger.info("开始批量读取股票基础数据,股票代码数量: {}", stockCodes.size());
long loadStart = System.currentTimeMillis();
List<TStockBasic> existingBasics = stockBasicService.selectStockBasicList(new TStockBasic());
// 将现有基础数据转换为Map以便快速查找
Map<String, TStockBasic> existingBasicsMap = new HashMap<>();
for (TStockBasic basic : existingBasics)
{
if (stockCodes.contains(basic.getStockCode()))
{
existingBasicsMap.put(basic.getStockCode(), basic);
}
}
long loadEnd = System.currentTimeMillis();
logger.info("股票基础数据读取完成,耗时: {} ms", (loadEnd - loadStart));
// 准备需要插入的数据
List<TStockBasic> newBasicsToInsert = new ArrayList<>();
logger.info("开始比较和分类股票基础数据");
long compareStart = System.currentTimeMillis();
for (TStockHighLowStatus stockHighLowStatus : stockHighLowStatusList)
{
TStockBasic existingBasic = existingBasicsMap.get(stockHighLowStatus.getStockCode());
if (existingBasic == null)
{
// 如果不存在,创建新的股票基础数据记录
// 对于新高新低状态,我们可能没有足够的信息来填充完整的股票基础数据
// 因此我们创建一个只有股票代码的最小记录
TStockBasic newBasic = new TStockBasic();
newBasic.setStockCode(stockHighLowStatus.getStockCode());
// 设置一些默认值以避免数据库约束错误
newBasic.setStockName(stockHighLowStatus.getStockCode()); // 使用股票代码作为名称
if (stockHighLowStatus.getIndustryIndexCode() != null && !stockHighLowStatus.getIndustryIndexCode().trim().isEmpty()) {
newBasic.setIndustryIndexCode(stockHighLowStatus.getIndustryIndexCode());
} else {
newBasic.setIndustryIndexCode("");
}
if (stockHighLowStatus.getIndustryIndexName() != null) {
newBasic.setIndustryIndexName(stockHighLowStatus.getIndustryIndexName());
} else {
newBasic.setIndustryIndexName("");
}
newBasic.setIsSt(0); // 默认不是ST股票
newBasic.setIsStarSt(0); // 默认不是*ST股票
// 注意:这里没有股票名称,所以我们使用股票代码作为名称或跳过插入
// 根据业务需求,我们可以选择不插入,或者使用股票代码作为名称
// 这里我们暂时只插入股票代码
if (stockHighLowStatus.getStockCode() != null)
{
newBasicsToInsert.add(newBasic);
}
}
// 不需要更新已有基础数据,因为新高新低状态没有提供相关信息
}
long compareEnd = System.currentTimeMillis();
logger.info("股票基础数据比较完成,耗时: {} ms", (compareEnd - compareStart));
// 批量插入新的股票基础数据
if (!newBasicsToInsert.isEmpty())
{
logger.info("准备批量插入 {} 条新的股票基础数据", newBasicsToInsert.size());
long insertStart = System.currentTimeMillis();
stockBasicService.importStockBasic(newBasicsToInsert); // 使用importStockBasic方法进行批量插入
long insertEnd = System.currentTimeMillis();
logger.info("股票基础数据插入完成,耗时: {} ms", (insertEnd - insertStart));
}
else
{
logger.info("无需插入新的股票基础数据");
}
long checkTime = System.currentTimeMillis();
logger.info("股票基础数据处理完成,耗时: {} ms", (checkTime - startTime));
// 批量插入新高新低状态数据
int count = 0;
int batchSize = 500;
// 分批导入数据
logger.info("开始批量插入新高新低状态数据,总记录数: {}", stockHighLowStatusList.size());
long statusDataStartTime = System.currentTimeMillis();
for (int i = 0; i < stockHighLowStatusList.size(); i += batchSize)
{
int end = Math.min(i + batchSize, stockHighLowStatusList.size());
List<TStockHighLowStatus> batchList = stockHighLowStatusList.subList(i, end);
count += stockHighLowStatusMapper.batchUpsertStockHighLowStatus(batchList);
int batchCount = stockHighLowStatusMapper.batchUpsertStockHighLowStatus(batchList);
count += batchCount;
logger.info("批次 [{}-{}] 新高新低状态数据插入完成,本次插入: {} 条", i, end, batchCount);
}
long statusDataEndTime = System.currentTimeMillis();
logger.info("新高新低状态数据批量插入完成,总插入: {} 条,耗时: {} ms", count, (statusDataEndTime - statusDataStartTime));
long totalTime = System.currentTimeMillis() - startTime;
logger.info("导入任务完成,总耗时: {} ms", totalTime);
return count;
}
@ -111,4 +275,4 @@ public class StockHighLowStatusServiceImpl implements IStockHighLowStatusService
{
return stockHighLowStatusMapper.selectNewLowStockList(stockHighLowStatus);
}
}
}

@ -0,0 +1,95 @@
package com.ruoyi.newstocksystem.service.impl;
import java.util.List;
import com.ruoyi.newstocksystem.mapper.TIndustryIndexMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.newstocksystem.mapper.TIndustryBasicMapper;
import com.ruoyi.newstocksystem.domain.TIndustryBasic;
import com.ruoyi.newstocksystem.service.ITIndustryBasicService;
/**
* Service
*
* @author lxy
* @date 2026-01-23
*/
@Service
public class TIndustryBasicServiceImpl implements ITIndustryBasicService
{
@Autowired
private TIndustryBasicMapper tIndustryBasicMapper;
/**
*
*
* @param industryCode
* @return
*/
@Override
public TIndustryBasic selectTIndustryBasicByCode(String industryCode)
{
return tIndustryBasicMapper.selectTIndustryBasicByCode(industryCode);
}
/**
*
*
* @param industryBasic
* @return
*/
@Override
public List<TIndustryBasic> selectTIndustryBasicList(TIndustryBasic industryBasic)
{
return tIndustryBasicMapper.selectTIndustryBasicList(industryBasic);
}
/**
*
*
* @param industryBasic
* @return
*/
@Override
public int insertTIndustryBasic(TIndustryBasic industryBasic)
{
return tIndustryBasicMapper.insertTIndustryBasic(industryBasic);
}
/**
*
*
* @param industryBasic
* @return
*/
@Override
public int updateTIndustryBasic(TIndustryBasic industryBasic)
{
return tIndustryBasicMapper.updateTIndustryBasic(industryBasic);
}
/**
*
*
* @param industryCodes
* @return
*/
@Override
public int deleteTIndustryBasicByCodes(String[] industryCodes)
{
return tIndustryBasicMapper.deleteTIndustryBasicByCodes(industryCodes);
}
/**
*
*
* @param industryBasicList
* @return
*/
@Override
public int importIndustryBasic(List<TIndustryBasic> industryBasicList)
{
return tIndustryBasicMapper.batchUpsertIndustryBasic(industryBasicList);
}
}

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.newstocksystem.mapper.TIndustryBasicMapper">
<resultMap type="com.ruoyi.newstocksystem.domain.TIndustryBasic" id="TIndustryBasicResult">
<result property="industryCode" column="industry_code" />
<result property="industryName" column="industry_name" />
<result property="industryLevel" column="industry_level" />
<result property="parentIndustryCode" column="parent_industry_code" />
<result property="description" column="description" />
<result property="status" column="status" />
<result property="sortOrder" column="sort_order" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectTIndustryBasicVo">
select industry_code, industry_name, industry_level, parent_industry_code, description, status, sort_order, create_time, update_time
from t_industry_basic
</sql>
<select id="selectTIndustryBasicByCode" parameterType="String" resultMap="TIndustryBasicResult">
<include refid="selectTIndustryBasicVo"/>
where industry_code = #{industryCode}
</select>
<select id="selectTIndustryBasicList" parameterType="com.ruoyi.newstocksystem.domain.TIndustryBasic" resultMap="TIndustryBasicResult">
<include refid="selectTIndustryBasicVo"/>
<where>
<if test="industryCode != null and industryCode != ''">
AND industry_code = #{industryCode}
</if>
<if test="industryName != null and industryName != ''">
AND industry_name like concat('%', #{industryName}, '%')
</if>
<if test="industryLevel != null ">
AND industry_level = #{industryLevel}
</if>
<if test="parentIndustryCode != null and parentIndustryCode != ''">
AND parent_industry_code = #{parentIndustryCode}
</if>
<if test="status != null ">
AND status = #{status}
</if>
</where>
order by sort_order asc
</select>
<insert id="insertTIndustryBasic" parameterType="com.ruoyi.newstocksystem.domain.TIndustryBasic" useGeneratedKeys="false">
insert into t_industry_basic
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="industryCode != null and industryCode != ''">
industry_code,
</if>
<if test="industryName != null and industryName != ''">
industry_name,
</if>
<if test="industryLevel != null">
industry_level,
</if>
<if test="parentIndustryCode != null">
parent_industry_code,
</if>
<if test="description != null">
description,
</if>
<if test="status != null">
status,
</if>
<if test="sortOrder != null">
sort_order,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="industryCode != null and industryCode != ''">
#{industryCode},
</if>
<if test="industryName != null and industryName != ''">
#{industryName},
</if>
<if test="industryLevel != null">
#{industryLevel},
</if>
<if test="parentIndustryCode != null">
#{parentIndustryCode},
</if>
<if test="description != null">
#{description},
</if>
<if test="status != null">
#{status},
</if>
<if test="sortOrder != null">
#{sortOrder},
</if>
</trim>
</insert>
<update id="updateTIndustryBasic" parameterType="com.ruoyi.newstocksystem.domain.TIndustryBasic">
update t_industry_basic
<trim prefix="SET" suffixOverrides=",">
<if test="industryName != null and industryName != ''">
industry_name = #{industryName},
</if>
<if test="industryLevel != null">
industry_level = #{industryLevel},
</if>
<if test="parentIndustryCode != null">
parent_industry_code = #{parentIndustryCode},
</if>
<if test="description != null">
description = #{description},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="sortOrder != null">
sort_order = #{sortOrder},
</if>
<if test="updateTime != null">
update_time = #{updateTime},
</if>
</trim>
where industry_code = #{industryCode}
</update>
<delete id="deleteTIndustryBasicByCode" parameterType="String">
delete from t_industry_basic where industry_code = #{industryCode}
</delete>
<delete id="deleteTIndustryBasicByCodes" parameterType="String">
delete from t_industry_basic where industry_code in
<foreach item="industryCode" collection="array" open="(" separator="," close=")">
#{industryCode}
</foreach>
</delete>
<insert id="batchUpsertIndustryBasic" parameterType="com.ruoyi.newstocksystem.domain.TIndustryBasic">
INSERT INTO t_industry_basic(
industry_code, industry_name, industry_level, parent_industry_code,
description, status, sort_order, create_time, update_time
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.industryCode}, #{item.industryName}, #{item.industryLevel},
#{item.parentIndustryCode}, #{item.description}, #{item.status},
#{item.sortOrder}, now(), now()
)
</foreach>
ON DUPLICATE KEY UPDATE
industry_name = VALUES(industry_name),
industry_level = VALUES(industry_level),
parent_industry_code = VALUES(parent_industry_code),
description = VALUES(description),
status = VALUES(status),
sort_order = VALUES(sort_order),
update_time = now()
</insert>
</mapper>

@ -0,0 +1,17 @@
-- 修改 t_industry_index 表,将外键指向新的行业基础表
ALTER TABLE `t_industry_index` DROP FOREIGN KEY `t_industry_index_ibfk_1`;
ALTER TABLE `t_industry_index` ADD CONSTRAINT `t_industry_index_ibfk_1`
FOREIGN KEY (`industry_index_code`) REFERENCES `t_industry_basic` (`industry_code`)
ON DELETE RESTRICT ON UPDATE CASCADE;
-- 修改 t_stock_basic 表,将外键指向新的行业基础表
ALTER TABLE `t_stock_basic` DROP FOREIGN KEY `t_stock_basic_ibfk_1`;
ALTER TABLE `t_stock_basic` ADD CONSTRAINT `t_stock_basic_ibfk_1`
FOREIGN KEY (`industry_index_code`) REFERENCES `t_industry_basic` (`industry_code`)
ON DELETE RESTRICT ON UPDATE CASCADE;
-- 如果有其他包含行业代码的表也需要做相应调整,例如:
-- ALTER TABLE `other_table` DROP FOREIGN KEY `other_table_ibfk_x`;
-- ALTER TABLE `other_table` ADD CONSTRAINT `other_table_ibfk_x`
-- FOREIGN KEY (`industry_code`) REFERENCES `t_industry_basic` (`industry_code`)
-- ON DELETE RESTRICT ON UPDATE CASCADE;

@ -0,0 +1,18 @@
-- 行业基础数据表:存储行业基础信息
CREATE TABLE `t_industry_basic` (
`industry_code` VARCHAR(20) NOT NULL COMMENT '行业代码如802089.EI',
`industry_name` VARCHAR(50) NOT NULL COMMENT '行业名称(如"银行"',
`industry_level` TINYINT NOT NULL DEFAULT 2 COMMENT '行业级别1=一级行业2=二级行业3=三级行业等)',
`parent_industry_code` VARCHAR(20) NULL COMMENT '父级行业代码',
`description` TEXT NULL COMMENT '行业描述',
`status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态1=正常0=禁用)',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-- 主键:行业代码
PRIMARY KEY (`industry_code`),
-- 索引:按行业级别查询优化
INDEX `idx_t_industry_basic_level` (`industry_level`),
-- 索引:按状态查询优化
INDEX `idx_t_industry_basic_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行业基础数据表';
Loading…
Cancel
Save