在實際開發中,一定會需要將資料持久化,常見的持久化技術有Spring 自帶的 JdbcTemplate 、Spring Boot 提供的 JPA 規範以及 MyBatis ,這個系列文會逐一介紹上述三種持久化技術,本篇文章先講最簡單的 JdbcTemplate

JDBC 與JdbcTemplate

JDBC ,全名為 Java Database Connectivity ,是一種 用於執行SQL 語法的Java API ,它將資料庫存取SQL 語法與Java API 分開,讓開發人員開發資料庫應用程式更有彈性。

JdbcTemplate 則是對 JDBC 的封裝,目的是為了解決 JDBC 每次使用都必須重新進行資料庫連接、處理SQL 語法、傳值、關閉資料庫連接等一系列操作所引發的一系列問題, 替開發人員完成了所有JDBC 的底層工作 ,因此使用 JdbcTemplate 就不用每次都進行連結、開啟、關閉等操作。

batchUpdate : 批量更新。 execute : 執行SQL 語法。 update : 執行一條插入、更新或刪除語法。 query : 查詢並返回相應值。 queryForList : 查詢並返回一個List。 queryForObject : 查詢並返回一個Object。 queryForMap : 查詢並返回一個Map。 queryForRowSet : 查詢並返回一個RowSet。

接下來會實作使用 JdbcTemplate 對資料庫進行 新增 查詢 修改 等操作,由於修改跟刪除都是使用 update 方法,這邊就不實作了,完整的程式碼就放在最下方的Github 連結。

<!-- MySQL Driver -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
<!-- JDBC API -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

配置資料庫連線

// 設定資料庫位址
spring.datasource.url=jdbc:mysql://localhost:3306/test_project?useUnicode=true&characeterEncoding=utf-8&serverTimezone=Asia/Shanghai
// 設定使用者資訊
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

建立資料表

CREATE TABLE IF NOT EXISTS member_account (
	ID INT PRIMARY KEY AUTO_INCREMENT COMMENT "會員流水號",
	USERNAME VARCHAR(60) UNIQUE NOT NULL COMMENT "帳號",
	PASSWORD VARCHAR(60) NOT NULL COMMENT "密碼",
	SALT VARCHAR(32) NOT NULL COMMENT "鹽值",
	CREATE_BY VARCHAR(60) NOT NULL COMMENT "建立者",
	CREATE_TIME DATETIME NOT NULL COMMENT "建立時間",
	UPDATE_BY VARCHAR(60) NOT NULL COMMENT "修改者",
	UPDATE_TIME DATETIME NOT NULL COMMENT "修改時間"
)DEFAULT CHARSET=utf8mb4

建立實體類

package com.example.demo.entity;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class MemberAccount extends Base {
	private String id;
	private String username;
	private String password;
	private String salt;

建立持久層接口

package com.example.demo.dao;
import com.example.demo.entity.MemberAccount;
public interface MemberAccountDao {
	public Integer insert(MemberAccount memberAccount);
	public MemberAccount findMemberAccountByUsername(String username);
	public Integer update(MemberAccount memberAccount);

建立持久層實作方法

package com.example.demo.dao.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import com.example.demo.dao.MemberAccountDao;
import com.example.demo.entity.MemberAccount;
@Repository
public class MemberAccountDaoImpl implements MemberAccountDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private NamedParameterJdbcTemplate jdbcNameTemplate;
	@Override
	public Integer insert(MemberAccount memberAccount) {
		// TODO Auto-generated method stub
		String sql = " INSERT INTO test_project.member_account ( "
				  	   + "		USERNAME, PASSWORD, SALT, "
				  	   + "		CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME "
				  	   + " ) "
				  	   + " VALUE ( "
				  	   + "		:username, :password, :salt, "
				  	   + "		:create_by, NOW(), :update_by, NOW() "
				  	   + " ) ";
		SqlParameterSource paramSource = new BeanPropertySqlParameterSource(memberAccount);
		KeyHolder keyHolder = new GeneratedKeyHolder();
		jdbcNameTemplate.update(sql, paramSource, keyHolder);
		return keyHolder.getKey().intValue();
	@Override
	public MemberAccount findMemberAccountByUsername(String username) {
		// TODO Auto-generated method stub
		String sql = " SELECT "
						   + "		ID, USERNAME, PASSWORD, SALT "
						   + " FROM "
						   + "		test_project.member_account "
						   + " WHERE "
						   + "		USERNAME = ? ";
		List<MemberAccount> result = jdbcTemplate.query(sql, new BeanPropertyRowMapper<MemberAccount>(MemberAccount.class), new Object[] { username });
		if(result != null && result.size() > 0) {
			return result.get(0);
		return null;
	@Override
	public Integer update(MemberAccount memberAccount) {
		// TODO Auto-generated method stub
		String sql = " UPDATE "
						   + "		test_project.member_account "
						   + " SET "
						   + "		PASSWORD = :password, UPDATE_BY = :update_by, UPDATE_TIME = NOW() "
						   + " WHERE "
						   + "		ID = :id ";
		SqlParameterSource paramSource = new BeanPropertySqlParameterSource(memberAccount);
		return jdbcNameTemplate.update(sql, paramSource);

單元測試方法

package com.example.demo.dao;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.example.demo.entity.MemberAccount;
@SpringBootTest
public class MemberAccountDaoTest {
	@Autowired
	private MemberAccountDao memberAccountDao;
	@Test
	public void insert() {
		MemberAccount memberAccount = new MemberAccount();
		memberAccount.setUsername("username@email.com");
		memberAccount.setPassword("password");
		String salt = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
		memberAccount.setSalt(salt);
		memberAccount.setCreate_by(memberAccount.getUsername());
		memberAccount.setUpdate_by(memberAccount.getUsername());
		Integer id = memberAccountDao.insert(memberAccount);
		System.out.println(id);
	@Test
	public void findMemberAccountByUsername() {
		String username = "username@email.com";
		MemberAccount memberAccount = memberAccountDao.findMemberAccountByUsername(username);
		if(memberAccount != null) System.out.println(memberAccount.toString());
	@Test
	public void update() {
		MemberAccount memberAccount = new MemberAccount();
		memberAccount.setId("1");
		memberAccount.setPassword("123456");
		memberAccount.setUpdate_by("username@email.com");
		Integer result = memberAccountDao.update(memberAccount);
		System.out.println(result);

Github

使用JDBC 建立持久層及其測試方法

(13) 甚麼是 JDBC、ORM、 JPA、ORM框架、Hibernate
JdbcTemplate (Spring Framework 5.3.10 API)