diff --git a/lab-14/lab-14-jdbctemplate/pom.xml b/lab-14/lab-14-jdbctemplate/pom.xml
new file mode 100644
index 00000000..2a18a5ea
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+ 4.0.0
+
+ lab-14-jdbctemplate
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+ 5.1.48
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
diff --git a/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/Application.java b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/Application.java
new file mode 100644
index 00000000..b68d996a
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/Application.java
@@ -0,0 +1,7 @@
+package cn.iocoder.springboot.lab14.jdbctemplate;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+}
diff --git a/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDao.java b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDao.java
new file mode 100644
index 00000000..6d38f974
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDao.java
@@ -0,0 +1,125 @@
+package cn.iocoder.springboot.lab14.jdbctemplate.dao;
+
+import cn.iocoder.springboot.lab14.jdbctemplate.dataobject.UserDO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+import org.springframework.stereotype.Repository;
+
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class UserDao {
+
+ /**
+ * 声明 INSERT 操作的 PreparedStatementCreatorFactory 对象
+ */
+ private static final PreparedStatementCreatorFactory INSERT_PREPARED_STATEMENT_CREATOR_FACTORY
+ = new PreparedStatementCreatorFactory("INSERT INTO users(username, password, create_time) VALUES(?, ?, ?)");
+
+ static {
+ // 设置返回主键
+ INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.setReturnGeneratedKeys(true);
+ INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.setGeneratedKeysColumnNames("id");
+ // 设置每个占位符的类型
+ INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.addParameter(new SqlParameter(Types.VARCHAR));
+ INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.addParameter(new SqlParameter(Types.VARCHAR));
+ INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.addParameter(new SqlParameter(Types.TIMESTAMP));
+ }
+
+ @Autowired
+ private JdbcTemplate template;
+
+ /**
+ * 使用 PreparedStatementCreator 实现插入数据
+ *
+ * @param entity 实体
+ * @return 影响行数
+ */
+ public int insert(UserDO entity) {
+ // 创建 KeyHolder 对象,设置返回的主键 ID
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+ // 执行插入操作
+ int updateCounts = template.update(INSERT_PREPARED_STATEMENT_CREATOR_FACTORY.newPreparedStatementCreator(
+ Arrays.asList(entity.getUsername(), entity.getPassword(), entity.getCreateTime())
+ ), keyHolder);
+ // 设置 ID 主键到 entity 实体中
+ if (keyHolder.getKey() != null) {
+ entity.setId(keyHolder.getKey().intValue());
+ }
+ // 返回影响行数
+ return updateCounts;
+ }
+
+ /**
+ * 使用 SimpleJdbcInsert 实现插入数据
+ *
+ * @param entity 实体
+ * @return 影响行数
+ */
+ public int insert0(UserDO entity) {
+ // 创建 SimpleJdbcInsert 对象
+ SimpleJdbcInsert insertOp = new SimpleJdbcInsert(template);
+ insertOp.setTableName("users");
+ insertOp.setColumnNames(Arrays.asList("username", "password", "create_time"));
+ insertOp.setGeneratedKeyName("id");
+ // 拼接参数
+ Map params = new HashMap<>();
+ params.put("username", entity.getUsername());
+ params.put("password", entity.getPassword());
+ params.put("create_time", entity.getCreateTime());
+ // 执行插入操作
+ Number id = insertOp.executeAndReturnKey(params);
+ // 设置 ID 主键到 entity 实体中
+ entity.setId(id.intValue());
+ // 返回影响行数
+ return 1;
+ }
+
+ public int updateById(UserDO entity) {
+ // JdbcTemplate 生成更新的动态 SQL 不是很方便,需要自己二次封装。类似 SimpleJdbcInsert 对象
+ return template.update("UPDATE users SET password = ? WHERE id = ?", entity.getPassword(),
+ entity.getId());
+ }
+
+ public int deleteById(Integer id) {
+ return template.update("DELETE FROM users WHERE id = ?", id);
+ }
+
+ public UserDO selectById(Integer id) {
+ return template.queryForObject("SELECT id, username, password, create_time FROM users WHERE id = ?",
+ new BeanPropertyRowMapper<>(UserDO.class), // 结果转换成对应的对象
+ id);
+ }
+
+ public UserDO selectByUsername(String username) {
+ return template.queryForObject("SELECT id, username, password, create_time FROM users WHERE username = ? LIMIT 1",
+ new BeanPropertyRowMapper<>(UserDO.class), // 结果转换成对应的对象
+ username);
+ }
+
+ public List selectByIds(List ids) {
+ // 创建 NamedParameterJdbcTemplate 对象
+ NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(template);
+ // 拼接参数
+ Map params = new HashMap<>();
+ params.put("ids", ids);
+ // 执行查询
+ return namedParameterJdbcTemplate.query(
+ "SELECT id, username, password, create_time FROM users WHERE id IN (:ids)", // 使用 :ids 作为占位服务
+ params,
+ new BeanPropertyRowMapper<>(UserDO.class) // 结果转换成对应的对象
+ );
+ }
+
+}
diff --git a/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dataobject/UserDO.java b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dataobject/UserDO.java
new file mode 100644
index 00000000..a71276d4
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/src/main/java/cn/iocoder/springboot/lab14/jdbctemplate/dataobject/UserDO.java
@@ -0,0 +1,74 @@
+package cn.iocoder.springboot.lab14.jdbctemplate.dataobject;
+
+import java.util.Date;
+
+/**
+ * 用户 DO
+ */
+public class UserDO {
+
+ /**
+ * 用户编号
+ */
+ private Integer id;
+ /**
+ * 账号
+ */
+ private String username;
+ /**
+ * 密码(明文)
+ *
+ * ps:生产环境下,千万不要明文噢
+ */
+ private String password;
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public UserDO setId(Integer id) {
+ this.id = id;
+ return this;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public UserDO setUsername(String username) {
+ this.username = username;
+ return this;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public UserDO setPassword(String password) {
+ this.password = password;
+ return this;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public UserDO setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "UserDO{" +
+ "id=" + id +
+ ", username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", createTime=" + createTime +
+ '}';
+ }
+}
diff --git a/lab-14/lab-14-jdbctemplate/src/main/resources/application.yaml b/lab-14/lab-14-jdbctemplate/src/main/resources/application.yaml
new file mode 100644
index 00000000..a7680349
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/src/main/resources/application.yaml
@@ -0,0 +1,7 @@
+spring:
+ # datasource 数据源配置内容
+ datasource:
+ url: jdbc:mysql://47.112.193.81:3306/testb5f4?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ driver-class-name: com.mysql.jdbc.Driver
+ username: testb5f4
+ password: F4df4db0ed86@11
diff --git a/lab-14/lab-14-jdbctemplate/src/test/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDaoTest.java b/lab-14/lab-14-jdbctemplate/src/test/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDaoTest.java
new file mode 100644
index 00000000..60331706
--- /dev/null
+++ b/lab-14/lab-14-jdbctemplate/src/test/java/cn/iocoder/springboot/lab14/jdbctemplate/dao/UserDaoTest.java
@@ -0,0 +1,69 @@
+package cn.iocoder.springboot.lab14.jdbctemplate.dao;
+
+import cn.iocoder.springboot.lab14.jdbctemplate.Application;
+import cn.iocoder.springboot.lab14.jdbctemplate.dataobject.UserDO;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class UserDaoTest {
+
+ @Autowired
+ private UserDao userDao;
+
+ @Test
+ public void testInsert() {
+ UserDO user = new UserDO().setUsername(UUID.randomUUID().toString())
+ .setPassword("nicai").setCreateTime(new Date());
+ userDao.insert(user);
+ System.out.println(user);
+ }
+
+ @Test
+ public void testInsert0() {
+ UserDO user = new UserDO().setUsername(UUID.randomUUID().toString())
+ .setPassword("nicai").setCreateTime(new Date());
+ userDao.insert0(user);
+ System.out.println(user);
+ }
+
+ @Test
+ public void testUpdateById() {
+ UserDO updateUser = new UserDO().setId(1)
+ .setPassword("wobucai");
+ userDao.updateById(updateUser);
+ }
+
+ @Test
+ public void testDeleteById() {
+ userDao.deleteById(2);
+ }
+
+ @Test
+ public void testSelectById() {
+ UserDO user = userDao.selectById(1);
+ System.out.println(user);
+ }
+
+ @Test
+ public void testSelectByUsername() {
+ UserDO user = userDao.selectByUsername("yunai");
+ System.out.println(user);
+ }
+
+ @Test
+ public void testSelectByIds() {
+ List users = userDao.selectByIds(Arrays.asList(1, 5));
+ System.out.println("users:" + users.size());
+ }
+
+}
diff --git a/lab-14/pom.xml b/lab-14/pom.xml
new file mode 100644
index 00000000..7c40a731
--- /dev/null
+++ b/lab-14/pom.xml
@@ -0,0 +1,19 @@
+
+
+
+ labs-parent
+ cn.iocoder.springboot.labs
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ lab-14
+ pom
+
+ lab-14-jdbctemplate
+
+
+
+