傳統 JDBC 需手動管理連線、預處理、結果集、異常轉換與資源釋放,樣板代碼繁瑣。Spring JDBC 以 JdbcTemplate 為核心,封裝底層細節,開發者僅需關注 SQL 與參數綁定,大幅提升開發效率與代碼可維護性。
SQLException 轉換為 Spring 統一的 DataAccessException 體系,免去強制捕獲。-- MySQL 建表腳本
CREATE TABLE Student (
ID INT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(20) NOT NULL,
AGE INT NOT NULL,
PRIMARY KEY (ID)
);
<!-- Spring XML 配置資料源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/TEST"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
public interface StudentDAO {
void setDataSource(DataSource ds);
void create(String name, Integer age);
Student getStudent(Integer id);
List<Student> listStudents();
}
public class Student {
private Integer id, age;
private String name;
// Getter/Setter 省略
}
public class StudentMapper implements RowMapper<Student> {
@Override
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
Student s = new Student();
s.setId(rs.getInt("id"));
s.setName(rs.getString("name"));
s.setAge(rs.getInt("age"));
return s;
}
}
public class StudentJDBCTemplate implements StudentDAO {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void create(String name, Integer age) {
String SQL = "INSERT INTO Student (name, age) VALUES (?, ?)";
jdbcTemplate.update(SQL, name, age);
System.out.println("Created: " + name + ", " + age);
}
@Override
public Student getStudent(Integer id) {
String SQL = "SELECT * FROM Student WHERE id = ?";
return jdbcTemplate.queryForObject(SQL, new Object[]{id}, new StudentMapper());
}
@Override
public List<Student> listStudents() {
String SQL = "SELECT * FROM Student";
return jdbcTemplate.query(SQL, new StudentMapper());
}
}
-- MySQL 預存程序
DELIMITER $$
CREATE PROCEDURE `getRecord` (
IN in_id INTEGER,
OUT out_name VARCHAR(20),
OUT out_age INTEGER
)
BEGIN
SELECT name, age INTO out_name, out_age FROM Student WHERE id = in_id;
END $$
DELIMITER ;
public class StudentJDBCTemplate implements StudentDAO {
private SimpleJdbcCall jdbcCall;
public void setDataSource(DataSource dataSource) {
this.jdbcCall = new SimpleJdbcCall(dataSource)
.withProcedureName("getRecord");
}
@Override
public Student getStudent(Integer id) {
SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);
Map<String, Object> out = jdbcCall.execute(in);
Student student = new Student();
student.setId(id);
student.setName((String) out.get("out_name"));
student.setAge((Integer) out.get("out_age"));
return student;
}
// create/listStudents 同前
}
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("Beans.xml");
StudentDAO dao = ctx.getBean("studentJDBCTemplate", StudentDAO.class);
dao.create("Zara", 11);
dao.create("Nuha", 2);
dao.create("Ayan", 15);
for (Student s : dao.listStudents()) {
System.out.printf("ID: %d, Name: %s, Age: %d%n", s.getId(), s.getName(), s.getAge());
}
}
}
Spring JDBC 以 JdbcTemplate 簡化資料存取,配合 RowMapper 實現物件映射,SimpleJdbcCall 支援跨資料庫預存程序,是輕量級 Java 專案資料層的優選方案。