qiangdanxitong/backend/src/main/java/com/designhub/service/ThirdPartyDbService.java

266 lines
9.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.designhub.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.designhub.entity.ThirdPartyDbConfig;
import com.designhub.exception.BusinessException;
import com.designhub.mapper.ThirdPartyDbConfigMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 第三方数据库服务
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ThirdPartyDbService {
private final ThirdPartyDbConfigMapper configMapper;
// 静态初始化块:移除 TLS 和证书算法限制,以支持旧版 SQL Server
static {
try {
// 完全移除 TLS 算法禁用限制
java.security.Security.setProperty("jdk.tls.disabledAlgorithms", "");
// 完全移除证书路径算法禁用限制(解决 Certificates do not conform to algorithm constraints 错误)
java.security.Security.setProperty("jdk.certpath.disabledAlgorithms", "");
// 设置允许的 TLS 协议
System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1.2");
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
log.info("已移除 TLS 和证书算法限制,支持旧版 SQL Server 连接");
} catch (Exception e) {
log.warn("移除算法限制失败: {}", e.getMessage());
}
}
/**
* 获取所有配置
*/
public List<ThirdPartyDbConfig> getAllConfigs() {
return configMapper.selectList(
new LambdaQueryWrapper<ThirdPartyDbConfig>()
.orderByDesc(ThirdPartyDbConfig::getCreateTime)
);
}
/**
* 获取配置详情
*/
public ThirdPartyDbConfig getConfigById(Long id) {
return configMapper.selectById(id);
}
/**
* 获取启用的配置
*/
public ThirdPartyDbConfig getEnabledConfig() {
return configMapper.selectOne(
new LambdaQueryWrapper<ThirdPartyDbConfig>()
.eq(ThirdPartyDbConfig::getEnabled, 1)
.last("LIMIT 1")
);
}
/**
* 创建配置
*/
@Transactional(rollbackFor = Exception.class)
public ThirdPartyDbConfig createConfig(ThirdPartyDbConfig config) {
config.setCreateTime(LocalDateTime.now());
config.setUpdateTime(LocalDateTime.now());
configMapper.insert(config);
return config;
}
/**
* 更新配置
*/
@Transactional(rollbackFor = Exception.class)
public ThirdPartyDbConfig updateConfig(ThirdPartyDbConfig config) {
config.setUpdateTime(LocalDateTime.now());
configMapper.updateById(config);
return config;
}
/**
* 删除配置
*/
@Transactional(rollbackFor = Exception.class)
public void deleteConfig(Long id) {
configMapper.deleteById(id);
}
/**
* 测试数据库连接
*/
public boolean testConnection(ThirdPartyDbConfig config) {
Connection conn = null;
try {
conn = getConnection(config);
return conn != null && !conn.isClosed();
} catch (Exception e) {
log.error("数据库连接测试失败: {}", e.getMessage());
return false;
} finally {
closeConnection(conn);
}
}
/**
* 获取数据库连接
*/
private Connection getConnection(ThirdPartyDbConfig config) throws SQLException {
String url;
String driverClass;
switch (config.getDbType().toLowerCase()) {
case "sqlserver":
driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
// 旧版SQL Server只支持TLS 1.0,强制使用TLS 1.0协议
url = String.format("jdbc:sqlserver://%s:%d;databaseName=%s;encrypt=false;trustServerCertificate=true;sslProtocol=TLSv1",
config.getHost(), config.getPort(), config.getDatabase());
// 设置系统属性以启用TLS 1.0
System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1.2");
break;
case "mysql":
driverClass = "com.mysql.cj.jdbc.Driver";
url = String.format("jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai",
config.getHost(), config.getPort(), config.getDatabase());
break;
case "postgresql":
driverClass = "org.postgresql.Driver";
url = String.format("jdbc:postgresql://%s:%d/%s",
config.getHost(), config.getPort(), config.getDatabase());
break;
default:
throw new BusinessException("不支持的数据库类型: " + config.getDbType());
}
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
throw new SQLException("数据库驱动未找到: " + driverClass);
}
int timeout = config.getConnectionTimeout() != null ? config.getConnectionTimeout() : 10;
DriverManager.setLoginTimeout(timeout);
return DriverManager.getConnection(url, config.getUsername(), config.getPassword());
}
/**
* 关闭连接
*/
private void closeConnection(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.error("关闭数据库连接失败", e);
}
}
}
/**
* 查询商品库存信息
* @param barcode 商品条码 (sku_id)
* @return 库存数量,如果未找到返回0
*/
public Map<String, Object> checkInventory(String barcode) {
ThirdPartyDbConfig config = getEnabledConfig();
if (config == null) {
throw new BusinessException("未配置第三方数据库或配置未启用");
}
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Map<String, Object> result = new HashMap<>();
result.put("barcode", barcode);
result.put("quantity", 0);
result.put("found", false);
try {
conn = getConnection(config);
// 查询聚水潭库存信息表
// 可用库存 = qty - order_lock - lock_qty
// 条件:wms_co_id='14138566',根据sku_id查询
String sql = "SELECT sku_id, qty, order_lock, lock_qty, " +
"qty - ISNULL(order_lock, 0) - ISNULL(lock_qty, 0) AS available_qty " +
"FROM jst_inventoryInfo WITH(NOLOCK) " +
"WHERE wms_co_id = '14138566' AND sku_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, barcode);
rs = pstmt.executeQuery();
if (rs.next()) {
int availableQty = rs.getInt("available_qty");
result.put("found", true);
result.put("skuId", rs.getString("sku_id"));
result.put("quantity", rs.getInt("qty"));
result.put("orderLock", rs.getInt("order_lock"));
result.put("lockQty", rs.getInt("lock_qty"));
result.put("availableQty", availableQty);
log.info("查询到商品库存: sku_id={}, qty={}, order_lock={}, lock_qty={}, available={}",
barcode, rs.getInt("qty"), rs.getInt("order_lock"), rs.getInt("lock_qty"), availableQty);
} else {
log.info("未找到商品库存信息: sku_id={}", barcode);
}
} catch (SQLException e) {
log.error("查询库存失败: sku_id={}, error={}", barcode, e.getMessage());
throw new BusinessException("查询库存失败: " + e.getMessage());
} finally {
try {
if (rs != null) rs.close();
if (pstmt != null) pstmt.close();
} catch (SQLException e) {
log.error("关闭资源失败", e);
}
closeConnection(conn);
}
return result;
}
/**
* 检查库存是否足够(库存大于1才能发布任务)
* @param barcode 商品条码
* @return 检查结果
*/
public Map<String, Object> checkInventoryForTask(String barcode) {
Map<String, Object> inventoryResult = checkInventory(barcode);
Map<String, Object> result = new HashMap<>(inventoryResult);
boolean found = (boolean) inventoryResult.get("found");
int availableQty = found ? (int) inventoryResult.getOrDefault("availableQty", 0) : 0;
// 库存大于1才允许发布
boolean canPublish = found && availableQty > 1;
result.put("canPublish", canPublish);
if (!found) {
result.put("message", "未找到该商品库存信息,请先申请样品");
} else if (availableQty <= 1) {
result.put("message", "商品库存不足(可用库存: " + availableQty + "),请先申请样品");
} else {
result.put("message", "库存充足(可用库存: " + availableQty + "),可以发布任务");
}
return result;
}
}