Spring 的 JdbcTemplate 和 JdbcDaoSupport

AngeliaZheng發表於2018-09-12

Spring JDBC 開發中,我們發現必須在所有DAO模式裡的查詢,插入,更新和刪除操作中建立大量的冗餘程式碼(建立連線,關閉連線,處理異常)。它的效率並不是很高,容易出錯和乏味。不過,我們可以使用 JdbcTemplate 和 JdbcDaoSupport 類來簡化整個資料庫的操作過程。

1. JdbcTemplate

1.1 JdbcTemplate插入操作

1.1.1 單條插入

private DataSource dataSource;
private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {
	this.dataSource = dataSource;
}
	
public void insert(Article article) {
	String sql = "INSERT INTO ARTICLE (ID, TITLE, CONTENT) VALUES (?, ?, ?)";
		
	jdbcTemplate = new JdbcTemplate(dataSource);
	jdbcTemplate.update(sql, new Object[]{article.getId(), article.getTitle(), article.getContent()});
}

1.1.2 批量插入

在某些情況下,可能需要將一批記錄插入到資料庫中。如果你對每條記錄呼叫一個外掛的方法,SQL語句將被重複編譯,造成系統緩慢進行。解決上述問題,可以使用 JdbcTemplate BATCHUPDATE()方法來執行批量插入操作。用這種方法,該語句只被編譯一次,執行多次。

public void insertArticles(final List<Article> articles) {
	String sql = "INSERT INTO ARTICLE (ID, TITLE, CONTENT) VALUES (?, ?, ?)";

	jdbcTemplate = new JdbcTemplate(dataSource);
	jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
		
		public void setValues(PreparedStatement ps, int i) throws SQLException {
			Article article = articles.get(i);
			ps.setLong(1, article.getId());
			ps.setString(2, article.getTitle());
			ps.setString(3, article.getContent());
		}

		public int getBatchSize() {
			return articles.size();
		}
	});
}

1.2 JdbcTemplate查詢

1.2.1 查詢單行資料

有兩種方法來查詢或從資料庫中提取單行記錄,並將其轉換成一個模型類。

  • 自定義RowMapper
  • BeanPropertyRowMapper

自定義RowMapper

建議實現 RowMapper 介面來建立自定義的RowMapper

public class ArticleRowMapper implements RowMapper<Article> {

	public Article mapRow(ResultSet rs, int rowNum) throws SQLException {
		return  new Article(rs.getInt("ID"), rs.getString("TITLE"), rs.getString("CONTENT"));
	}
}

 傳遞給 queryForObject()方法,返回的結果將呼叫自定義 mapRow()方法的值匹配到屬性。

public Article getArticleById(int id) {
	String sql = "SELECT * FROM ARTICLE WHERE ID = ?";
		
	jdbcTemplate = new JdbcTemplate(dataSource);
	return jdbcTemplate.queryForObject(sql, new Object[]{id}, new ArticleRowMapper());
}

BeanPropertyRowMapper

public Article getArticleById(int id) {
	String sql = "SELECT * FROM ARTICLE WHERE ID = ?";
		
	jdbcTemplate = new JdbcTemplate(dataSource);
	return jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<Article>(Article.class));
}

使用BeanPropertyRowMapper,需要在實體類Article裡有預設的建構函式。負責初始化Article失敗。

1.2.2 查詢多行

手動對映

由於 RowMapper 不支援 queryForList()方法,需要手動對映它。

public List<Article> getArticles() {
	String sql = "SELECT * FROM ARTICLE";
	jdbcTemplate = new JdbcTemplate(dataSource);

	List<Article> articles = new ArrayList<Article>();

	List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
	for (Map row : rows) {
		Article article = new Article((Long)row.get("ID"), (String)row.get("TITLE"), (String)row.get("CONTENT"));
		articles.add(article);
	}
	
	return articles;
}

BeanPropertyRowMapper

public List<Article> getArticles() {
	String sql = "SELECT * FROM ARTICLE";
	jdbcTemplate = new JdbcTemplate(dataSource);
	return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Article>(Article.class));
}

2. JdbcDaoSupport

通過擴充套件 JdbcDaoSupport,設定資料來源,並且 JdbcTemplate 在類中不再是必需的,只需要正確的資料來源注入DAO。就可以使用 getJdbcTemplate()方法得到 JdbcTemplate。

public class JdbcArticleDao extends JdbcDaoSupport implements ArticleDao {

	/*private DataSource dataSource;
	private JdbcTemplate jdbcTemplate;

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}*/

	public void insert(Article article) {
		String sql = "INSERT INTO ARTICLE (ID, TITLE, CONTENT) VALUES (?, ?, ?)";

		//jdbcTemplate = new JdbcTemplate(dataSource);
		getJdbcTemplate().update(sql, new Object[]{article.getId(), article.getTitle(), article.getContent()});
	}

	public List<Article> getArticles() {
		String sql = "SELECT * FROM ARTICLE";
		//bcTemplate = new JdbcTemplate(dataSource);
		return getJdbcTemplate().query(sql, new BeanPropertyRowMapper<Article>(Article.class));
	}

	public Article getArticleById(int id) {
		String sql = "SELECT * FROM ARTICLE WHERE ID = ?";

		//jdbcTemplate = new JdbcTemplate(dataSource);
		return getJdbcTemplate().queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<Article>(Article.class));
	}
}

相關文章