From d6ad9c4838466c39ec0555852a718a1583dda4d3 Mon Sep 17 00:00:00 2001 From: Lxy Date: Fri, 23 Jan 2026 00:37:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=201=E3=80=81=E5=A2=9E=E5=8A=A0=E8=A1=8C?= =?UTF-8?q?=E4=B8=9A=E5=9F=BA=E7=A1=80=E6=95=B0=E6=8D=AE=E8=A1=A8=EF=BC=9B?= =?UTF-8?q?2=E3=80=81=E8=B0=83=E6=95=B4=E6=89=80=E6=9C=89=E8=A1=8C?= =?UTF-8?q?=E4=B8=9A=E6=8C=87=E6=95=B0=E6=95=B0=E6=8D=AE=E5=85=B3=E8=81=94?= =?UTF-8?q?=E7=9A=84=E5=A4=96=E9=94=AE=EF=BC=9B3=E3=80=81=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=AF=8F=E6=97=A5=E4=B8=AA=E8=82=A1=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=97=B6=EF=BC=8C=E6=A3=80=E6=9F=A5=E4=B8=AA?= =?UTF-8?q?=E8=82=A1=E5=9F=BA=E7=A1=80=E6=95=B0=E6=8D=AE=E5=92=8C=E8=A1=8C?= =?UTF-8?q?=E4=B8=9A=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=B9=B6=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=92=8C=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../newstocksystem/domain/TIndustryBasic.java | 130 +++++++++ .../domain/TStockDailyTrade.java | 67 +++++ .../mapper/TIndustryBasicMapper.java | 69 +++++ .../service/IIndustryIndexService.java | 19 +- .../service/ITIndustryBasicService.java | 61 ++++ .../impl/IndustryIndexServiceImpl.java | 61 ++-- .../impl/StockDailyTradeServiceImpl.java | 268 +++++++++++++++++- .../impl/StockHighLowStatusServiceImpl.java | 170 ++++++++++- .../impl/TIndustryBasicServiceImpl.java | 95 +++++++ .../newstocksystem/TIndustryBasicMapper.xml | 162 +++++++++++ .../alter_tables_for_industry_basic.sql | 17 ++ sql_refacor0120/t_industry_basic.sql | 18 ++ 12 files changed, 1098 insertions(+), 39 deletions(-) create mode 100644 newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TIndustryBasic.java create mode 100644 newstock-system/src/main/java/com/ruoyi/newstocksystem/mapper/TIndustryBasicMapper.java create mode 100644 newstock-system/src/main/java/com/ruoyi/newstocksystem/service/ITIndustryBasicService.java create mode 100644 newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/TIndustryBasicServiceImpl.java create mode 100644 newstock-system/src/main/resources/mapper/newstocksystem/TIndustryBasicMapper.xml create mode 100644 sql_refacor0120/alter_tables_for_industry_basic.sql create mode 100644 sql_refacor0120/t_industry_basic.sql diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TIndustryBasic.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TIndustryBasic.java new file mode 100644 index 0000000..0eb3a7b --- /dev/null +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TIndustryBasic.java @@ -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 + + '}'; + } +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TStockDailyTrade.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TStockDailyTrade.java index 0f30c2c..3fc6581 100644 --- a/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TStockDailyTrade.java +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/domain/TStockDailyTrade.java @@ -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 + '}'; } } diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/mapper/TIndustryBasicMapper.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/mapper/TIndustryBasicMapper.java new file mode 100644 index 0000000..3d4ef0c --- /dev/null +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/mapper/TIndustryBasicMapper.java @@ -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 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 industryBasicList); +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/IIndustryIndexService.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/IIndustryIndexService.java index 85bee7d..2d01d9e 100644 --- a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/IIndustryIndexService.java +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/IIndustryIndexService.java @@ -77,4 +77,21 @@ public interface IIndustryIndexService * @return 交易日期列表 */ public List selectTradeDates(); -} + + /** + * 检查行业基础数据是否存在 + * + * @param industryCode 行业代码 + * @return 存在返回true,否则返回false + */ + public boolean checkIndustryBasicExists(String industryCode); + + /** + * 创建行业基础数据记录 + * + * @param industryCode 行业代码 + * @param industryName 行业名称 + * @return 结果 + */ + public int createIndustryBasic(String industryCode, String industryName); +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/ITIndustryBasicService.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/ITIndustryBasicService.java new file mode 100644 index 0000000..13d6c9b --- /dev/null +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/ITIndustryBasicService.java @@ -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 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 industryBasicList); +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/IndustryIndexServiceImpl.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/IndustryIndexServiceImpl.java index d6d69db..252e100 100644 --- a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/IndustryIndexServiceImpl.java +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/IndustryIndexServiceImpl.java @@ -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 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 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); + } +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockDailyTradeServiceImpl.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockDailyTradeServiceImpl.java index 46b8f21..d2d5cb6 100644 --- a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockDailyTradeServiceImpl.java +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockDailyTradeServiceImpl.java @@ -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 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 stockCodes = new HashSet<>(); + for (TStockDailyTrade stockDailyTrade : stockDailyTradeList) + { + stockCodes.add(stockDailyTrade.getStockCode()); + } + + // 一次性读取所有存在的股票基础数据 + logger.info("开始批量读取股票基础数据,股票代码数量: {}", stockCodes.size()); + long loadStart = System.currentTimeMillis(); + + List existingBasics = stockBasicService.selectStockBasicList(new TStockBasic()); + + // 将现有基础数据转换为Map以便快速查找 + Map 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 newBasicsToInsert = new ArrayList<>(); + List 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 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); } -} +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockHighLowStatusServiceImpl.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockHighLowStatusServiceImpl.java index f1e9952..016c31e 100644 --- a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockHighLowStatusServiceImpl.java +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/StockHighLowStatusServiceImpl.java @@ -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 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 stockCodes = new HashSet<>(); + for (TStockHighLowStatus stockHighLowStatus : stockHighLowStatusList) + { + stockCodes.add(stockHighLowStatus.getStockCode()); + } + + // 一次性读取所有存在的股票基础数据 + logger.info("开始批量读取股票基础数据,股票代码数量: {}", stockCodes.size()); + long loadStart = System.currentTimeMillis(); + + List existingBasics = stockBasicService.selectStockBasicList(new TStockBasic()); + + // 将现有基础数据转换为Map以便快速查找 + Map 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 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 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); } -} +} \ No newline at end of file diff --git a/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/TIndustryBasicServiceImpl.java b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/TIndustryBasicServiceImpl.java new file mode 100644 index 0000000..024254a --- /dev/null +++ b/newstock-system/src/main/java/com/ruoyi/newstocksystem/service/impl/TIndustryBasicServiceImpl.java @@ -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 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 industryBasicList) + { + return tIndustryBasicMapper.batchUpsertIndustryBasic(industryBasicList); + } +} \ No newline at end of file diff --git a/newstock-system/src/main/resources/mapper/newstocksystem/TIndustryBasicMapper.xml b/newstock-system/src/main/resources/mapper/newstocksystem/TIndustryBasicMapper.xml new file mode 100644 index 0000000..4ece4b6 --- /dev/null +++ b/newstock-system/src/main/resources/mapper/newstocksystem/TIndustryBasicMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + select industry_code, industry_name, industry_level, parent_industry_code, description, status, sort_order, create_time, update_time + from t_industry_basic + + + + + + + + insert into t_industry_basic + + + industry_code, + + + industry_name, + + + industry_level, + + + parent_industry_code, + + + description, + + + status, + + + sort_order, + + + + + #{industryCode}, + + + #{industryName}, + + + #{industryLevel}, + + + #{parentIndustryCode}, + + + #{description}, + + + #{status}, + + + #{sortOrder}, + + + + + + update t_industry_basic + + + industry_name = #{industryName}, + + + industry_level = #{industryLevel}, + + + parent_industry_code = #{parentIndustryCode}, + + + description = #{description}, + + + status = #{status}, + + + sort_order = #{sortOrder}, + + + update_time = #{updateTime}, + + + where industry_code = #{industryCode} + + + + delete from t_industry_basic where industry_code = #{industryCode} + + + + delete from t_industry_basic where industry_code in + + #{industryCode} + + + + + INSERT INTO t_industry_basic( + industry_code, industry_name, industry_level, parent_industry_code, + description, status, sort_order, create_time, update_time + ) VALUES + + ( + #{item.industryCode}, #{item.industryName}, #{item.industryLevel}, + #{item.parentIndustryCode}, #{item.description}, #{item.status}, + #{item.sortOrder}, now(), now() + ) + + 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() + + + \ No newline at end of file diff --git a/sql_refacor0120/alter_tables_for_industry_basic.sql b/sql_refacor0120/alter_tables_for_industry_basic.sql new file mode 100644 index 0000000..c169133 --- /dev/null +++ b/sql_refacor0120/alter_tables_for_industry_basic.sql @@ -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; \ No newline at end of file diff --git a/sql_refacor0120/t_industry_basic.sql b/sql_refacor0120/t_industry_basic.sql new file mode 100644 index 0000000..71d3813 --- /dev/null +++ b/sql_refacor0120/t_industry_basic.sql @@ -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='行业基础数据表'; \ No newline at end of file