对于一些小的项目, 我们没有必要使用MyBatis/JPA/Hibernate等重量级技术, 直接使用Spring JDBC 即可, Spring JDBC 是对 jdbc的简单封装, 很容易掌握.

============================
Spring JdbcTemplate 和 JDBC API 对比
============================
JDBC API的缺点:
1. 我们的代码中包含充斥着很多这样的代码: 创建connection, 创建statement , 关闭connection, 关闭resultset.
2. 对于 resultset 操作也不太方便, 需要使用 while 循环 + 客户端游标.next() 等.
3. 实现 Row -> Object 的映射比较玛法.
3. 我们需要自己控制 transaction(老实说, 这既是缺点又是优点)

Spring JdbcTemplate的特点:
1. 不需要我们关注各种资源的打开/关闭
2. 很容易将 resultset 转成 Pojo 集合.
3. 自动能利用上 DB 连接池

============================
Spring Jdbc主要类
============================
JdbcTemplate 类: 这是Spring JDBC中最常用的类.
NamedParameterJdbcTemplate 类: Jdbc中传统的参数占位符是问号, 这个类提供对命名参数的支持.
SimpleJdbcInsert 类: 不需要写Insert语句,即可完成单表插入操作, 该类支持链式调用(fluent style)
SimpleJdbcCall 类: 简化的调用存储过程的类, 该类支持链式调用(fluent style)

一般情况下, 我们使用 JdbcTemplate 或 NamedParameterJdbcTemplate 类就足够了.

============================
JdbcTemplate 主要方法
============================
query(),最通用的Select查询,  如果要返回一个  List<UserDefinedClass)  形式的结果集, 必须使用 query() 方法. 
queryForList()/queryForMap()/queryForRowSet(), 以集合的形式保存Select查询结果, queryForList()的结果不是 List<UserDefinedClass) 类型, 而是 List<Map> 类型, 每行记录一个 Map 对象, 字段和字段值以 K-V的形式保存. 
queryForObject(): 用来获得Select 标量值, 结果必须是一列一行.
execute(): 多用来执行DDL操作, 也可以用来执行 DML 语句.
update(): 用来执行Insert/Update/Delete操作
call():执行存储过程
batchUpdate(): 批量执行增删改操作

============================
pom.xml & application.properties & DB
============================

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
#application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=toor
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

在示例中使用了MySQL 官方提供的 sakila 样本数据库, 该数据用来模拟DVD租赁业务.

先 clone 一个actor_new 新表.

CREATE TABLE `actor_new` (
`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`actor_id`),
KEY `idx_actor_last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8 insert into actor_new select * from actor ;

============================
java 示例代码
============================

package com.example.demo;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate; @SpringBootApplication
public class JdbcSampleApplication implements CommandLineRunner {
@Autowired
DataSource dataSource; @Autowired
JdbcTemplate jdbcTemplate; TransactionTemplate transTemplate; /*
* 该方法会被Spring自动在合适的时机调用, 用来初始化一个 TransactionTemplate 对象. 参数 dataSource 被自动注入.
*/
@Autowired
private void transactionTemplate(DataSource dataSource) {
transTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource));
} public static void main(String[] args) throws Exception {
SpringApplication.run(JdbcSampleApplication.class, args);
} @Override
public void run(String... args) throws Exception {
runSimpleSamples();
runRowToObjectSample();
runTransactionSamples();
runBatchSamples();
} /*
* 将resultset 转成 Java 对象列表
*/
public void runRowToObjectSample() {
String querySql = "select * from actor_new where actor_id<?";
int id = 20; // 查询DB,
List<Actor> actors = jdbcTemplate.query(querySql, new Object[] { id }, new ActorRowMapper());
for (Actor actor : actors) {
System.out.println(actor.getFirstName());
}
} /*
* Query/DML执行
*/
public void runSimpleSamples() throws SQLException {
// 标量查询
Integer count = jdbcTemplate.queryForObject("Select count(*) from actor_new", Integer.class);
System.out.println(String.format("actor_new record count:%d", count)); // DML执行
jdbcTemplate.update("Delete from actor_new where actor_id=?", 2); count = jdbcTemplate.queryForObject("Select count(*) from actor_new", Integer.class);
System.out.println(String.format("actor_new record count:%d", count));
} /*
* 带有事务控制的DML
* 将DML操作放到 TransactionCallback类的doInTransaction()方法中.
* 只有在下面两种情况下才会回滚:
* 1. 通过设置 transactionStatus 为 RollbackOnly
* 2. 抛出任何异常
* */
public void runTransactionSamples() throws SQLException { transTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
// DML执行
jdbcTemplate.update("Delete from actor_new where actor_id=?", 3); // 回滚
transactionStatus.setRollbackOnly();
return null;
}
}); } /*
* 批量update
* */
public void runBatchSamples() throws SQLException {
//多个SQL批量提交
String sql1="delete from actor_new where actor_id>=1000";
String sql2="Insert into actor_new(actor_id, first_name, last_name) values (1000,'Harry','Liu')";
jdbcTemplate.batchUpdate(sql1,sql2); //将 List<Actor> 对象集合插入的DB中.
List<Actor> actors=new ArrayList<Actor>();
actors.add(new Actor("A1","B1"));
actors.add(new Actor("A2","B2"));
actors.add(new Actor("A3","B3"));
actors.add(new Actor("A4","B4"));
actors.add(new Actor("A5","B5"));
String sql3="Insert into actor_new(first_name, last_name) values (?,?)";
jdbcTemplate.batchUpdate(sql3, new BatchPreparedStatementSetter() { @Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
// TODO Auto-generated method stub
//设置 PreparedStatement 的参数, 参数下标从 1 开始
ps.setString(1, actors.get(i).getFirstName());
ps.setString(2, actors.get(i).getLastName());
} @Override
public int getBatchSize() {
// TODO Auto-generated method stub
return 3;
}
}); //使用 batchArgs 集合将多个 actor 插入DB.
String sql3="Insert into actor_new(first_name, last_name) values (?,?)";
List<Object[]> batchArgs = new ArrayList<Object[]>();
batchArgs.add(new Object[]{"A6","B6"});
batchArgs.add(new Object[]{"A7","B7"});
jdbcTemplate.batchUpdate(sql3,batchArgs);
} } /*
* Actor entity 类
*/
class Actor {
private int actorId;
private String firstName;
private String lastName;
private Timestamp lastUpdateTimestamp; public Actor() {
} public Actor(String firstName, String lastName) {
this.firstName=firstName;
this.lastName=lastName;
} public int getActorId() {
return actorId;
} public void setActorId(int actorId) {
this.actorId = actorId;
} public String getFirstName() {
return firstName;
} public void setFirstName(String firstName) {
this.firstName = firstName;
} public String getLastName() {
return lastName;
} public void setLastName(String lastName) {
this.lastName = lastName;
} public Timestamp getLastUpdateTimestamp() {
return lastUpdateTimestamp;
} public void setLastUpdateTimestamp(Timestamp lastUpdateTimestamp) {
this.lastUpdateTimestamp = lastUpdateTimestamp;
}
} /*
* 将Row 转成 Actor 的Mapper类
*/
class ActorRowMapper implements RowMapper<Actor> { @Override
public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setActorId(rs.getInt("actor_id"));
actor.setFirstName(rs.getString("First_name"));
actor.setLastName(rs.getString("last_name"));
actor.setLastUpdateTimestamp(rs.getTimestamp("last_update"));
return actor;
} }

============================
参考
============================
https://blog.csdn.net/zq9017197/article/details/6321391?utm_source=blogxgwz0

Spring JDBC
https://www.baeldung.com/spring-jdbc-jdbctemplate

Spring JdbcTemplate方法详解
https://blog.csdn.net/dyllove98/article/details/7772463

TRANSACTIONS WITH JDBCTEMPLATE
http://www.javacreed.com/transactions-with-jdbctemplate/

SpringBoot系列: JdbcTemplate 快速入门的更多相关文章

  1. SpringBoot系列: RestTemplate 快速入门

    ====================================相关的文章====================================SpringBoot系列: 与Spring R ...

  2. Flask开发系列之快速入门

    Flask开发系列之快速入门 文档 一个最小的应用 调试模式 路由 变量规则 构造 URL HTTP 方法 静态文件 模板渲染 访问请求数据 环境局部变量 请求对象 文件上传 Cookies 重定向和 ...

  3. Springboot 完整搭建快速入门,必看!

    前言 手把手教你Springboot微服务项目搭建快速入门,通过本文学习Springboot的搭建快速入门,掌握微服务大致的配置服务,后续将会继续将核心组件引入到项目中,欢迎关注,点赞,转发. Spr ...

  4. BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序

    BIML 101 - BIML 快速入门教程 做大数据的项目,最花时间的就是数据清洗. 没有一个相对可靠的数据,数据分析就是无木之舟,无水之源. 如果你已经进了ETL这个坑,而且预算有限,并且有大量的 ...

  5. SpringBoot整合ActiveMQ快速入门

    Spring Boot 具有如下特性: 为基于 Spring 的开发提供更快的入门体验 开箱即用,没有代码生成,也无需 XML 配置.同时也可以修改默认值来满足特定的需求. 提供了一些大型项目中常见的 ...

  6. springboot笔记02——快速入门quickstart

    前言 学习一个新的框架,往往会用一个quickstart快速入门,这次就写一下springboot的quickstart程序. 开发环境 JDK 1.8 Springboot 2.1.6 Maven ...

  7. SpringBoot简介与快速入门

    一.SpringBoot简介 1.1 原有Spring优缺点分析 1.1.1 Spring的优点分析 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE ...

  8. SpringBoot系列之从入门到精通系列教程

    对应SpringBoot系列博客专栏,例子代码,本博客不定时更新 Spring框架:作为JavaEE框架领域的一款重要的开源框架,在企业应用开发中有着很重要的作用,同时Spring框架及其子框架很多, ...

  9. BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 连接数据库执行SQL语句

    BIML 101 - BIML 快速入门教程 第一节 连接数据库执行SQL语句 本小节将用BIML建一个简单的可以执行的包. 新建一个biml文件,贴入下面的代码 1 <Biml xmlns=& ...

随机推荐

  1. OKR相关4本书,好书3本

    最近几年看过4本OKR相关的书,有3本是4星.其中第一本是最近看的,剩下3本是2017年看的. OKR源自德鲁克和格鲁夫,跟谷歌是天作之合:4星|<这就是OKR> 4星|<OKR实践 ...

  2. 我的第一个python web开发框架(33)——接口代码重构

    前面ORM模块我们已经完成了开发,接下来要做的就是对项目代码进行重构了.因为对底层数据库操作模块(db_helper.py)进行了改造,之前项目的接口代码全都跑不起来了. 在写ORM模块时,我们已经对 ...

  3. 1.3 Windows注册表

    如何打开Windows注册表呢? 方法一:Win+R打开命令行,再输入regetdit,回车. 方法二:打开计算机,进入系统所在盘,进入Windows\System32文件夹,找到regedt32,双 ...

  4. 【转】从源码分析Handler的postDelayed为什么可以延时?

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/aliankg/article/details/70842494Thread/Hander/Loope ...

  5. day22---面向对象基础初识

    面向过程编程: 核心是过程两个字,指的是解决问题的步骤,即先干什么再干什么,基于面向过程设计的程序就好比在设计一条流水线,是一种机械的思维方式. 优点:复杂问题流程化, 缺点:程序的可扩展性差 面向对 ...

  6. (转)lwip TCP client & FreeRTOS 打开TCP 的 保活机制 LWIP_TCP_KEEPALIVE==1

    参考大神教程:http://blog.sina.com.cn/s/blog_62a85b950101aw8x.html   老衲五木 :http://blog.sina.com.cn/s/blog_6 ...

  7. BZOJ1000-1099板刷计划+一句话题解 73/100

    1000-1009 1000A+B Problem 这个还要写??? 1001 狼抓兔子 平面图最小割转化为对偶图最短路 #include<bits/stdc++.h> #define i ...

  8. Educational Codeforces Round 62 (Rated for Div. 2) Solution

    最近省队前联考被杭二成七南外什么的吊锤得布星,拿一场Div. 2恢复信心 然后Div.2 Rk3.Div. 1+Div. 2 Rk9,rating大涨200引起舒适 现在的Div. 2都怎么了,最难题 ...

  9. 基于HTML5 的互联网+地铁行业

    前言 近几年,互联网与交通运输的融合,改变了交易模式,影响着运输组织和经营方式,改变了运输主体的市场结构.模糊了运营与非营运的界限,也更好的实现了交通资源的集约共享,同时使得更多依靠外力和企业推动交通 ...

  10. Winform让扫描枪听话,防止在有焦点的地方就扫码输入的尴尬

    关注点: 1.扫描枪在扫描到条码后会在有焦点的地方显示扫描到的条码并且可设置扫码后添加回车换行让我很尴尬 2.怎样拦截扫码输入,扫描到条码就自动会嘀一声.不要这么智能行不行.瞎BB 需求详解 公司生产 ...