Java注意事项
Java 注意事项
本篇文章 编写规定,以问题描述为标题 ,下方附带解决方法以及处理时间/代码图片/关键词/相关url
标题须采用## ,提供代码段,相关图例
1.针对表数据同步至另一张表,存在则update、不存在则insert
老办法 (废弃):
>> 通过对目标表数据进行主键一一查询判断
缺点:
性能方面:
频繁查询与操作:在代码里,针对查询结果集中的每条记录,都会单独执行一次查询来判断记录是否存在,接着再执行插入或者更新操作。当数据量较大时,会产生大量的数据库交互,这会显著降低性能,同时增加数据库的负载。
缺乏批量操作:代码没有运用批量插入或者批量更新的功能。批量操作可以减少与数据库的交互次数,从而提升性能。例如,在 MySQL 中可以使用 INSERT INTO ... ON DUPLICATE KEY UPDATE 语句来实现批量的 “存在则更新,不存在则插入” 操作。
// 通过 Db 获取数据库连接(Hutool 管理连接,避免泄漏)
try (Connection conn = Db.use().getConnection()) {
// 1. 查询源表数据(手动使用 PreparedStatement)
String selectSql = "SELECT id, rname, money FROM HZMY_LOG where id =2";
try (PreparedStatement selectStmt = conn.prepareStatement(selectSql)) {
try (ResultSet rs = selectStmt.executeQuery()) {
// 2. 遍历源表数据
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("rname");
int age = rs.getInt("money");
// 3. 检查目标表是否存在该记录
String checkSql = "SELECT id FROM HZMY_LOG_copy1 WHERE id = ?";
try (PreparedStatement checkStmt = conn.prepareStatement(checkSql)) {
checkStmt.setInt(1, id);
try (ResultSet checkRs = checkStmt.executeQuery()) {
if (checkRs.next()) {
// 存在则更新
String updateSql = "UPDATE HZMY_LOG_copy1 SET rname = ?, money = ? WHERE id = ?";
try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) {
updateStmt.setString(1, name);
updateStmt.setInt(2, age);
updateStmt.setInt(3, id);
updateStmt.executeUpdate();
}
} else {
// 不存在则插入
String insertSql = "INSERT INTO HZMY_LOG_copy1 (id, rname, money) VALUES (?, ?, ?)";
try (PreparedStatement insertStmt = conn.prepareStatement(insertSql)) {
insertStmt.setInt(1, id);
insertStmt.setString(2, name);
insertStmt.setInt(3, age);
insertStmt.executeUpdate();
}
}
}
}
}
}
}
System.out.println("所有记录处理完成");
} catch (SQLException e) {
System.err.println("数据库操作失败:" + e.getMessage());
e.printStackTrace();
}
MERGE INTO 进行完成此需求
优点
批量操作:MERGE INTO 可以在单个事务中完成多个操作,这对于大量数据的插入、更新或删除非常有用。这通常比分别执行 INSERT、UPDATE 和 DELETE 语句要快得多,因为这样可以减少数据库的锁定和日志开销。
MERGE INTO MID_ORG_Job AS target
USING (
SELECT
a.OId AS ID,
a.name AS NAME,
a.Code AS CODE,
a.order_emp AS SORT,
NULL AS UNITID,
a.Status AS IS_ENABLE,
a.stdIsDeleted AS IS_DELETED,
a.ModifiedTime AS UPDATE_TIME
FROM BeiSenJob a
WHERE a.stdIsDeleted = '0' AND a.Status = '1'
) AS source
ON target.ID = source.ID
WHEN MATCHED THEN
UPDATE SET
target.NAME = source.NAME,
target.CODE = source.CODE,
target.SORT = source.SORT,
target.UNITID = source.UNITID,
target.IS_ENABLE = source.IS_ENABLE,
target.IS_DELETED = source.IS_DELETED,
target.UPDATE_TIME = source.UPDATE_TIME
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID, NAME, CODE, SORT, UNITID, IS_ENABLE, IS_DELETED, UPDATE_TIME)
VALUES (
source.ID, source.NAME, source.CODE, source.SORT,
source.UNITID, source.IS_ENABLE, source.IS_DELETED, source.UPDATE_TIME
);
2.sql内容过多?如何优化处理?
使用sql文件进行内容管理,可创建resources/sql/*.sql 文件,在项目中进行读取使用
.main{
String mergeSql = loadSql("sync_job.sql");
}
private String loadSql(String filename) {
try {
ClassPathResource resource = new ClassPathResource(SQL_PATH + filename);
return StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
} catch (IOException e) {
logger.error("加载 SQL 文件失败:{}", filename, e);
throw new RuntimeException("无法加载 SQL 文件:" + filename, e);
}
}
3.定时任务数量太多?yml通用管理
使用yml配置文件进行统一管理,例如当有很多的定时任务时
@Component
public class PersonSyncTask {
//使用yml 进行批量管理 使用yml路径内容进行
@Scheduled(cron = "${cron.sync.person}")
public void sync() {
String mergeSql = loadSql("sync_person.sql");
executeMerge("MIDXXX同步", mergeSql);
}
}
在application.yml中添加
#MID同步任务 定时区域
cron:
sync:
person: "0 25 */1 * * ?"
unit: "0 26 */1 * * ?"
post: "0 27 */1 * * ?"
department: "0 28 */1 * * ?"
job: "0 29 */1 * * ?"
同时还可使用 封装执行器为统一接口或抽象类
public interface DataSyncTask {
void sync();
}
增加开关控制与重试机制(可选)
feature:
sync:
enable-person: true
enable-unit: true
retry-count: 3
在任务中判断是否启用:
@Value("${feature.sync.enable-person}")
private boolean enablePersonSync;
@Scheduled(cron = "...")
public void syncPerson() {
if (!enablePersonSync) return;
...
}```
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 枫月Blog
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果