本文延續 JDBC 系列,通過完整的 Emp 實體類與 EmpDAO 數據訪問對象,演示 INSERT 新增員工、UPDATE 修改薪資的標準流程,重點講解參數封裝、SQL 拼接風險、事務邊界與資源關閉模式。
遵循 JavaBean 規範:私有字段 + 公共 Getter/Setter + 無參構造器 + 全參構造器,實現數據庫表列與對象屬性一對一映射。
public class Emp {
private int empNo;
private String ename;
private String job;
private int mgr;
private String hiredate; // 建議用 LocalDate (Java 8+) 或 Date
private double sal;
private double comm;
private int deptno;
// ... Getter/Setter/Constructors 省略
}
設計原則:將表字段封裝為對象屬性,避免方法參數列表過長 (8 字段 → 1 個對象),提高可讀性與擴展性。
public void add(Emp emp) {
String sql = "INSERT INTO emp(empno, ename, job, mgr, hiredate, sal, comm, deptno) " +
"VALUES (?, ?, ?, ?, STR_TO_DATE(?, '%Y-%m-%d'), ?, ?, ?)";
// 使用 PreparedStatement 防注入,佔位符對應 setter
try (Connection con = ConnectionSource.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setInt(1, emp.getEmpNo());
ps.setString(2, emp.getEname());
ps.setString(3, emp.getJob());
ps.setInt(4, emp.getMgr());
ps.setString(5, emp.getHiredate()); // 格式 yyyy-MM-dd
ps.setDouble(6, emp.getSal());
ps.setDouble(7, emp.getComm());
ps.setInt(8, emp.getDeptno());
int rows = ps.executeUpdate();
if (rows > 0) System.out.println("新增記錄成功!ID: " + emp.getEmpNo());
} catch (SQLException e) {
throw new RuntimeException("數據庫訪問異常", e);
}
}
關鍵點:
PreparedStatement 而非字符串拼接,徹底防止 SQL 注入。STR_TO_DATE(?, '%Y-%m-%d') 處理字符串日期。finally。public void update(Emp emp) {
String sql = "UPDATE emp SET sal = ?, comm = ? WHERE empno = ?";
try (Connection con = ConnectionSource.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setDouble(1, emp.getSal());
ps.setDouble(2, emp.getComm());
ps.setInt(3, emp.getEmpNo());
int rows = ps.executeUpdate();
if (rows > 0) System.out.println("更新記錄成功!ID: " + emp.getEmpNo());
} catch (SQLException e) {
throw new RuntimeException("數據庫訪問異常", e);
}
}
public static void main(String[] args) {
EmpDAO dao = new EmpDAO();
// 1. 查詢所有
dao.findAll();
// 2. 新增
Emp emp = new Emp(1001, "rose", "Analyst", 7901, "2014-05-01", 3000.00, 500.00, 10);
dao.add(emp);
// 3. 更新薪資
emp.setSal(4500.00);
dao.update(emp);
}
控制台輸出確認新增與更新成功,數據庫表數據同步變更。
Duplicate entry '1001' for key 'PRIMARY'。解決:測試前清理數據、使用自增主鍵、或捕獲異常處理。STR_TO_DATE 格式字符串完全匹配。\"... VALUES (\" + emp.getEmpNo() + \", ...\" 極易注入,**生產代碼禁止使用**。ConnectionSource。