更新开始时间2
This commit is contained in:
@@ -18,7 +18,7 @@ public class CompletedToday {
|
|||||||
private String betId; //
|
private String betId; //
|
||||||
|
|
||||||
@Column(name = "time", nullable = false)
|
@Column(name = "time", nullable = false)
|
||||||
private String time; //
|
private Date time; //
|
||||||
|
|
||||||
//下注金额
|
//下注金额
|
||||||
@Column(name = "bet_amount", nullable = false)
|
@Column(name = "bet_amount", nullable = false)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.Optional;
|
|||||||
public interface CompletedTodayRepository extends JpaRepository<CompletedToday, Long> {
|
public interface CompletedTodayRepository extends JpaRepository<CompletedToday, Long> {
|
||||||
|
|
||||||
// 根据时间范围查询resultAmount的总和
|
// 根据时间范围查询resultAmount的总和
|
||||||
|
//Double sumResultAmountByCreateTimeAfter(Date startTime);
|
||||||
@Query("SELECT SUM(ct.resultAmount) FROM CompletedToday ct WHERE ct.time > :startTime")
|
@Query("SELECT SUM(ct.resultAmount) FROM CompletedToday ct WHERE ct.time > :startTime")
|
||||||
Double sumResultAmountByCreateTimeAfter(@Param("startTime") Date startTime);
|
Double sumResultAmountByCreateTimeAfter(@Param("startTime") Date startTime);
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class CrawlerSchedule {
|
|||||||
|
|
||||||
|
|
||||||
// 每7秒执行一次爬取今日已经结算
|
// 每7秒执行一次爬取今日已经结算
|
||||||
//@Scheduled(cron = "*/7 * * * * ?")
|
@Scheduled(cron = "*/7 * * * * ?")
|
||||||
public void executeSettlement() {
|
public void executeSettlement() {
|
||||||
System.out.println("开始爬取今日已经结算...");
|
System.out.println("开始爬取今日已经结算...");
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ import us.codecraft.webmagic.selector.Html;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -289,14 +292,34 @@ public class CompletedTodayCrawler implements PageProcessor {
|
|||||||
/**
|
/**
|
||||||
* 转换数据结构以适应数据库
|
* 转换数据结构以适应数据库
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* 转换数据结构以适应数据库(使用Java 8日期时间API)
|
||||||
|
*/
|
||||||
private List<CompletedToday> convertForDatabase(List<Map<String, Object>> betList) {
|
private List<CompletedToday> convertForDatabase(List<Map<String, Object>> betList) {
|
||||||
List<CompletedToday> completedTodayList = new ArrayList<>();
|
List<CompletedToday> completedTodayList = new ArrayList<>();
|
||||||
|
|
||||||
|
// 根据你实际的日期字符串格式调整
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
for (Map<String, Object> bet : betList) {
|
for (Map<String, Object> bet : betList) {
|
||||||
CompletedToday completedToday = new CompletedToday();
|
CompletedToday completedToday = new CompletedToday();
|
||||||
|
|
||||||
completedToday.setBetId((String) bet.get("bet_id"));
|
completedToday.setBetId((String) bet.get("bet_id"));
|
||||||
completedToday.setTime((String) bet.get("time"));
|
|
||||||
|
// 转换String时间到Date
|
||||||
|
try {
|
||||||
|
String timeStr = (String) bet.get("time");
|
||||||
|
// 将LocalDateTime转换为Date
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, formatter);
|
||||||
|
Date timeDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
completedToday.setTime(timeDate);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 处理日期解析异常,这里设置为当前时间作为默认值
|
||||||
|
completedToday.setTime(new Date());
|
||||||
|
// 也可以记录日志
|
||||||
|
System.err.println("日期解析失败: " + bet.get("time"));
|
||||||
|
}
|
||||||
|
|
||||||
completedToday.setBetAmount((Double)bet.get("bet_amount"));
|
completedToday.setBetAmount((Double)bet.get("bet_amount"));
|
||||||
completedToday.setResultAmount((Double) bet.get("result_amount"));
|
completedToday.setResultAmount((Double) bet.get("result_amount"));
|
||||||
completedToday.setResult((String) bet.get("result"));
|
completedToday.setResult((String) bet.get("result"));
|
||||||
@@ -307,6 +330,7 @@ public class CompletedTodayCrawler implements PageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存HTML用于调试
|
* 保存HTML用于调试
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -191,15 +191,16 @@ public class SQLiteUtil {
|
|||||||
/**
|
/**
|
||||||
* 批量插入今日完结数据
|
* 批量插入今日完结数据
|
||||||
*/
|
*/
|
||||||
public static boolean saveCompletedToday(List<CompletedToday> list) {
|
/* public static boolean saveCompletedToday(List<CompletedToday> list) {
|
||||||
if (list == null || list.isEmpty()) return false;
|
if (list == null || list.isEmpty()) return false;
|
||||||
|
|
||||||
String sql = """
|
String sql = """
|
||||||
INSERT OR IGNORE INTO completed_today
|
INSERT OR IGNORE INTO completed_today
|
||||||
(bet_id, time, bet_amount, result, result_amount, create_time, update_time)
|
(bet_id, time, bet_amount, result, result_amount, create_time, update_time)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, datetime(?), ?, ?, ?, ?, ?)
|
||||||
""";
|
""";
|
||||||
|
// 使用ISO8601格式: yyyy-MM-dd HH:mm:ss
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
try (Connection conn = getConnection();
|
try (Connection conn = getConnection();
|
||||||
PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
@@ -209,14 +210,18 @@ public class SQLiteUtil {
|
|||||||
if (data == null || data.getBetId() == null) continue;
|
if (data == null || data.getBetId() == null) continue;
|
||||||
|
|
||||||
pstmt.setString(1, data.getBetId());
|
pstmt.setString(1, data.getBetId());
|
||||||
pstmt.setString(2, data.getTime());
|
// 核心修复:毫秒转秒+setLong传入,适配datetime(?),无setString
|
||||||
|
if (data.getTime() != null) {
|
||||||
|
long secondTs = data.getTime().getTime() / 1000; // 毫秒→秒级时间戳
|
||||||
|
pstmt.setLong(2, secondTs);
|
||||||
|
} else {
|
||||||
|
long secondTs = System.currentTimeMillis() / 1000; // 空值兜底当前秒级时间
|
||||||
|
pstmt.setLong(2, secondTs);
|
||||||
|
}
|
||||||
pstmt.setDouble(3, data.getBetAmount() != null ? data.getBetAmount() : 0.0);
|
pstmt.setDouble(3, data.getBetAmount() != null ? data.getBetAmount() : 0.0);
|
||||||
pstmt.setString(4, data.getResult() != null ? data.getResult() : "未知");
|
pstmt.setString(4, data.getResult() != null ? data.getResult() : "未知");
|
||||||
pstmt.setDouble(5, data.getResultAmount() != null ? data.getResultAmount() : 0.0);
|
pstmt.setDouble(5, data.getResultAmount() != null ? data.getResultAmount() : 0.0);
|
||||||
|
|
||||||
// 使用ISO8601格式: yyyy-MM-dd HH:mm:ss
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
// 处理create_time
|
// 处理create_time
|
||||||
if (data.getCreateTime() != null) {
|
if (data.getCreateTime() != null) {
|
||||||
pstmt.setString(6, sdf.format(data.getCreateTime()));
|
pstmt.setString(6, sdf.format(data.getCreateTime()));
|
||||||
@@ -242,8 +247,144 @@ public class SQLiteUtil {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入今日完结数据(终极稳定版:解决SQLite datetime()解析问题+非空约束+批量插入)
|
||||||
|
*/
|
||||||
|
public static boolean saveCompletedToday(List<CompletedToday> list) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
System.out.println("[SQL日志] 待插入数据为空,直接返回");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 核心:删除datetime()函数,直接插入标准时间字符串
|
||||||
|
String sql = """
|
||||||
|
INSERT OR REPLACE INTO completed_today
|
||||||
|
(bet_id, time, bet_amount, result, result_amount, create_time, update_time)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""";
|
||||||
|
// 全局统一标准时间格式(SQL兼容,yyyy-MM-dd HH:mm:ss,支持所有时间查询)
|
||||||
|
SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
int validDataCount = 0;
|
||||||
|
Connection conn = null;
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
conn = getConnection();
|
||||||
|
if (conn == null) {
|
||||||
|
System.err.println("[SQL日志] 获取数据库连接失败!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pstmt = conn.prepareStatement(sql);
|
||||||
|
conn.setAutoCommit(false); // 开启事务
|
||||||
|
|
||||||
|
// 打印基础信息
|
||||||
|
System.out.println("[SQL日志] 待执行SQL:" + sql.replaceAll("\\s+", " "));
|
||||||
|
System.out.println("[SQL日志] 原始传入数据量:" + list.size());
|
||||||
|
|
||||||
|
for (CompletedToday data : list) {
|
||||||
|
// 过滤无效数据(含空串校验)
|
||||||
|
if (data == null || data.getBetId() == null || data.getBetId().trim().isEmpty()) {
|
||||||
|
System.out.println("[SQL日志] 过滤无效数据:data为null 或 bet_id为null/空串");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
validDataCount++;
|
||||||
|
|
||||||
|
// 1. bet_id:唯一标识
|
||||||
|
pstmt.setString(1, data.getBetId().trim());
|
||||||
|
|
||||||
|
// 核心修复:Java层格式化为标准时间字符串,直接传入(无datetime(),彻底解决非空)
|
||||||
|
String timeStr;
|
||||||
|
if (data.getTime() != null) {
|
||||||
|
timeStr = timeFormat.format(data.getTime());
|
||||||
|
} else {
|
||||||
|
timeStr = timeFormat.format(new Date()); // 空值兜底当前时间
|
||||||
|
}
|
||||||
|
pstmt.setString(2, timeStr);
|
||||||
|
|
||||||
|
// 3. 下注金额:空值兜底0.0
|
||||||
|
Double betAmount = data.getBetAmount() != null ? data.getBetAmount() : 0.0;
|
||||||
|
pstmt.setDouble(3, betAmount);
|
||||||
|
|
||||||
|
// 4. 输赢结果:空值兜底"未知"
|
||||||
|
String result = data.getResult() != null ? data.getResult().trim() : "未知";
|
||||||
|
pstmt.setString(4, result);
|
||||||
|
|
||||||
|
// 5. 输赢金额:空值兜底0.0
|
||||||
|
Double resultAmount = data.getResultAmount() != null ? data.getResultAmount() : 0.0;
|
||||||
|
pstmt.setDouble(5, resultAmount);
|
||||||
|
|
||||||
|
// 6. 创建时间:空值兜底当前时间
|
||||||
|
String createTime = data.getCreateTime() != null ? timeFormat.format(data.getCreateTime()) : timeFormat.format(new Date());
|
||||||
|
pstmt.setString(6, createTime);
|
||||||
|
|
||||||
|
// 7. 更新时间:空值兜底当前时间
|
||||||
|
String updateTime = data.getUpdateTime() != null ? timeFormat.format(data.getUpdateTime()) : timeFormat.format(new Date());
|
||||||
|
pstmt.setString(7, updateTime);
|
||||||
|
|
||||||
|
// 打印单条参数日志(含最终存入的time字符串)
|
||||||
|
System.out.printf("[SQL日志] 批量参数%d:bet_id=%s, time=%s, bet_amount=%.2f, result=%s, result_amount=%.2f, create_time=%s, update_time=%s%n",
|
||||||
|
validDataCount, data.getBetId(), timeStr, betAmount, result, resultAmount, createTime, updateTime);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验有效数据量
|
||||||
|
if (validDataCount == 0) {
|
||||||
|
System.out.println("[SQL日志] 无有效批量数据,执行回滚");
|
||||||
|
conn.rollback();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
System.out.println("[SQL日志] 有效批量数据量(已加入Batch):" + validDataCount);
|
||||||
|
|
||||||
|
// 执行批量插入并统计结果
|
||||||
|
int[] executeResults = pstmt.executeBatch();
|
||||||
|
int successCount = 0;
|
||||||
|
for (int res : executeResults) {
|
||||||
|
if (res == java.sql.Statement.SUCCESS_NO_INFO || res > 0) {
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn.commit(); // 提交事务
|
||||||
|
System.out.println("[SQL日志] 批量插入成功:总执行条数=" + executeResults.length + ",实际插入/替换条数=" + successCount);
|
||||||
|
return successCount > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
// 打印完整异常信息
|
||||||
|
System.err.println("[SQL异常] 批量插入失败,原因:");
|
||||||
|
System.err.println("错误码(ErrorCode):" + e.getErrorCode());
|
||||||
|
System.err.println("异常信息:" + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
// 异常回滚(判断自动提交模式)
|
||||||
|
try {
|
||||||
|
if (conn != null && !conn.getAutoCommit()) {
|
||||||
|
conn.rollback();
|
||||||
|
System.out.println("[SQL日志] 异常触发事务回滚成功");
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
System.err.println("[SQL异常] 事务回滚失败:" + ex.getMessage());
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
// 手动关闭资源,恢复连接状态
|
||||||
|
try {
|
||||||
|
if (pstmt != null) pstmt.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.setAutoCommit(true); // 恢复自动提交
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭数据库资源
|
* 关闭数据库资源
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user