You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
7.6 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.chaozhou;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
/**
* @ClassName ArchiveSync
* @Description
* @Author linjj
* @Date 2025/9/26 16:17
* @Version 1.0
*/
@Slf4j
public class ArchiveSync {
/* 读取当天全部病例 */
private static final String SQL_ORA_TODAY =
"SELECT ID号,住院号,住院次数,姓名,性别,入院时间,入院科室编码," +
"主管医生工号,年龄,身份证号,出院日期,当前科室编码 " +
"FROM PORTAL_HIS.V_WZHGD_HZJCXX h " +
"WHERE 出院日期 >= TRUNC(SYSDATE) " + // 今天 00:00:00
"AND 出院日期 < TRUNC(SYSDATE) + 1"; // 明天 00:00:00不含
/* SQL Server当天已归档主键 */
private static final String SQL_MSS_TODAY_KEYS =
"SELECT inp_no + '|' + CAST(visit_id AS VARCHAR) AS key1 " +
"FROM archive_master " +
"WHERE CONVERT(date, discharge_date_time) = CONVERT(date, GETDATE())";
/* 写入 SQL Server */
private static final String SQL_MSS_INSERT =
"INSERT INTO archive_master " +
"(id, patient_id, inp_no, visit_id, name, sex, dept_admission_to, " +
" admission_date_time, discharge_date_time, DOCTOR_IN_CHARGE, SubAssort, ID_NO, " +
" dept_name,id_card,ArchiveState,C1) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, '64','ljj')";
/* MySQL根据工号查询医生姓名 */
private static final String SQL_MYSQL_DOCTOR_NAME =
"SELECT name FROM power_user WHERE user_name = ?";
/* 当前最大 id */
private static final String SQL_MAX_ID = "SELECT ISNULL(MAX(id), 0) FROM archive_master";
public static void main(String[] args) throws Exception {
Properties cfg = new Properties();
try (InputStream in = ArchiveSync.class.getResourceAsStream("/application.properties")) {
cfg.load(in);
}
while (true) {
try (Connection ora = getConn(cfg, "oracle");
Connection mss = getConn(cfg, "sqlserver");
Connection mysql = getConn(cfg, "mysql"); // 新增 MySQL 连接
PreparedStatement psOra = ora.prepareStatement(SQL_ORA_TODAY);
PreparedStatement psKeys = mss.prepareStatement(SQL_MSS_TODAY_KEYS);
PreparedStatement psMaxId = mss.prepareStatement(SQL_MAX_ID);
PreparedStatement psIns = mss.prepareStatement(SQL_MSS_INSERT)) {
/*取 SQL Server 当天已归档主键 */
Set<String> archivedToday = new HashSet<>();
try (ResultSet rs = psKeys.executeQuery()) {
while (rs.next()) archivedToday.add(rs.getString(1));
}
log.info("SQL Server 当天已存在 {} 条", archivedToday.size());
/* 获取当前最大 id */
ResultSet rsMax = psMaxId.executeQuery();
rsMax.next();
long baseId = rsMax.getLong(1);
rsMax.close();
/*查询 Oracle 缺失数据 */
ResultSet rs = psOra.executeQuery();
int total = 0, insert = 0;
while (rs.next()) {
total++;
String key = rs.getString("住院号") + "|" + rs.getString("住院次数");
if (archivedToday.contains(key)) continue; // 已归档,跳过
psIns.setLong(1, baseId + (++insert)); // id
psIns.setString(2, rs.getString("ID号")); // patient_id
psIns.setString(3, rs.getString("住院号")); // inp_no
psIns.setString(4, rs.getString("住院次数")); // visit_id
psIns.setNString(5, rs.getString("姓名")); // name
// 取出 Oracle 值
String sexOra = rs.getString("性别");
// 字典转换
String sexMss;
if (sexOra == null || sexOra.trim().isEmpty()) {
sexMss = "不详";
} else if ("1".equals(sexOra)) {
sexMss = "男";
} else if ("2".equals(sexOra)) {
sexMss = "女";
} else {
sexMss = sexOra;
}
psIns.setNString(6, sexMss); // 对应 archive_master.sex
psIns.setNString(7, rs.getString("入院科室编码")); // dept_admission_to
psIns.setTimestamp(8, rs.getTimestamp("入院时间")); // admission_date_time
psIns.setTimestamp(9, rs.getTimestamp("出院日期")); // discharge_date_time
/* 查询 MySQL 获取医生姓名 */
String doctorCode = rs.getString("主管医生工号");
String doctorName = doctorCode; // 默认用编码
if (doctorCode != null && !doctorCode.trim().isEmpty()) {
try (PreparedStatement psDoctor = mysql.prepareStatement(SQL_MYSQL_DOCTOR_NAME)) {
psDoctor.setString(1, doctorCode.trim());
try (ResultSet rsDoctor = psDoctor.executeQuery()) {
if (rsDoctor.next()) {
String nameFromMysql = rsDoctor.getString("name");
// 仅当查询到非空姓名时才替换
if (nameFromMysql != null && !nameFromMysql.trim().isEmpty()) {
doctorName = nameFromMysql;
}
}
} catch (SQLException e) {
log.info("查询医生姓名失败,工号: {}", doctorCode, e);
}
}
}
psIns.setString(10, doctorName); // 将查询到的姓名存入 DOCTOR_IN_CHARGE 字段
psIns.setNString(11, rs.getString("年龄")); // SubAssort
psIns.setString(12, rs.getString("身份证号")); // id_card
psIns.setString(13, rs.getString("当前科室编码")); // dept_name
psIns.setString(14, rs.getString("身份证号")); // ID_NO
psIns.addBatch();
if (insert % 1000 == 0) psIns.executeBatch();
}
if (insert % 1000 != 0) psIns.executeBatch();
mss.commit();
log.info("Oracle 当天共 {} 条,缺失 {} 条,已插入 {} 条", total, insert, insert);
} catch (SQLException e) {
log.error("同步异常", e);
Thread.sleep(5000);
}
Thread.sleep(Integer.parseInt(System.getProperty("poll.interval", "30")) * 1000L);
}
}
/* 工具:根据前缀拿连接 */
private static Connection getConn(Properties cfg, String db) throws SQLException {
String url = cfg.getProperty(db + ".url");
String user = cfg.getProperty(db + ".user");
String pwd = cfg.getProperty(db + ".password");
return DriverManager.getConnection(url, user, pwd);
}
}