Spring JdbcTemplate
教程
Spring JdbcTemplate
教程展示了如何使用 Spring 的JdbcTemplate
处理数据。 我们是 MySQL 数据库。 我们创建使用JdbcTemplate
的经典 Spring 和 Spring Boot 应用。 ZetCode 拥有用于 MySQL Java 的完整电子书,其中包含扩展的JdbcTemplate
章节: MySQL Java 编程电子书。
目录
- 在 MySQL 中创建数据库
- Maven 依赖项
queryForObject()
方法RowMapper
BeanPropertyRowMapper
queryForList()
方法- 使用命名参数
- 使用
JdbcTemplate
的经典 Spring - 使用
JdbcTemplate
的 Spring Boot
Spring
Spring 是流行的 Java 应用框架。 JdbcTemplate
是用于简化 JDBC 编程的工具。 它处理乏味且容易出错的底层细节,例如处理事务,清理资源以及正确处理异常。 JdbcTemplate
包含在 Spring 的spring-jdbc
模块中。 Spring Boot 是 Spring 的解决方案,用于创建独立的,生产级的基于 Spring 的应用。
MySQL 是一个开源关系数据库管理系统。 它是最受欢迎的数据库之一。 它通常在 Web 应用中使用。
MySQL 创建数据库
我们使用mysql
监视器创建一个新的testdb
数据库。
cars_mysql.sql
DROP TABLE IF EXISTS cars;
CREATE TABLE cars(id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255), price INTEGER) ENGINE=InnoDB;
INSERT INTO cars(name, price) VALUES('Audi', 52642);
INSERT INTO cars(name, price) VALUES('Mercedes', 57127);
INSERT INTO cars(name, price) VALUES('Skoda', 9000);
INSERT INTO cars(name, price) VALUES('Volvo', 29000);
INSERT INTO cars(name, price) VALUES('Bentley', 350000);
INSERT INTO cars(name, price) VALUES('Citroen', 21000);
INSERT INTO cars(name, price) VALUES('Hummer', 41400);
INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);
这是在 MySQL 中创建cars
表的 SQL。
要创建数据库和表,我们使用mysql
监视工具。
$ sudo service mysql start
MySQL 用sudo service mysql start
命令启动。
$ mysql -u user7 -p
我们使用mysql
监视器连接到数据库。
mysql> CREATE DATABASE testdb;
Query OK, 1 row affected (0.02 sec)
使用CREATE DATABASE
语句创建一个新数据库。
mysql> USE testdb;
mysql> SOURCE cars_mysql.sql
使用source
命令,加载并执行cars_mysql.sql
文件。
mysql> SELECT * FROM cars;
+----+------------+--------+
| id | name | price |
+----+------------+--------+
| 1 | Audi | 52642 |
| 2 | Mercedes | 57127 |
| 3 | Skoda | 9000 |
| 4 | Volvo | 29000 |
| 5 | Bentley | 350000 |
| 6 | Citroen | 21000 |
| 7 | Hummer | 41400 |
| 8 | Volkswagen | 21600 |
+----+------------+--------+
8 rows in set (0.00 sec)
我们验证数据。
Maven 依赖
对于我们的应用,我们需要下载数据库驱动程序和 Spring 模块。 我们使用 Maven 做到这一点。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
这将下载spring-jdbc
模块。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
这是 MySQL 驱动程序的 Maven 依赖关系。
queryForObject()
方法
queryForObject()
方法执行 SQL 查询并返回结果对象。 结果类型在参数中指定。
com/zetcode/SpringDBQueryObjectEx.java
package com.zetcode;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class SpringDBQueryObjectEx {
public static void main(String[] args) throws SQLException {
var ds = new SimpleDriverDataSource();
ds.setDriver(new com.mysql.jdbc.Driver());
ds.setUrl("jdbc:mysql://localhost:3306/testdb");
ds.setUsername("user7");
ds.setPassword("s$cret");
var sql = "SELECT COUNT(*) FROM cars";
var jtm = new JdbcTemplate(ds);
int numOfCars = jtm.queryForObject(sql, Integer.class);
System.out.format("There are %d cars in the table", numOfCars);
}
}
在示例中,我们使用queryForObject()
方法获取cars
表中的汽车数量。
var sql = "SELECT COUNT(*) FROM cars";
该 SQL 返回cars
表中的行数。
int numOfCars = jtm.queryForObject(sql, Integer.class);
queryForObject()
方法的第二个参数指定结果的类型; 在我们的案例中是Integer
。
行映射器
RowMapper
逐行映射结果集的行。 此接口的实现执行将每一行映射到结果对象的实际工作。
com/zetcode/model/Car.java
package com.zetcode.model;
import java.util.Objects;
public class Car {
private Long id;
private String name;
private int price;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return price == car.price &&
Objects.equals(id, car.id) &&
Objects.equals(name, car.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, price);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Car{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", price=").append(price);
sb.append('}');
return sb.toString();
}
}
我们有一个Car
bean。 它具有id
,name
和price
属性。
com/zetcode/SpringDBRowMapper.java
package com.zetcode;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.zetcode.model.Car;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
public class SpringDBRowMapper {
public static void main(String[] args) throws SQLException {
var ds = new SimpleDriverDataSource();
ds.setDriver(new com.mysql.jdbc.Driver());
ds.setUrl("jdbc:mysql://localhost:3306/testdb");
ds.setUsername("user7");
ds.setPassword("s$cret");
var rm = (RowMapper<Car>) (ResultSet result, int rowNum) -> {
var car = new Car();
car.setId(result.getLong("id"));
car.setName(result.getString("name"));
car.setPrice(result.getInt("price"));
return car;
};
var sql = "SELECT * FROM cars WHERE id=?";
Long id = 1L;
var jtm = new JdbcTemplate(ds);
var car = (Car) jtm.queryForObject(sql, new Object[]{id}, rm);
System.out.println(car);
}
}
在示例中,我们使用RowMapper
将结果集的行映射到Car
对象。
var rm = (RowMapper<Car>) (ResultSet result, int rowNum) -> {
var car = new Car();
car.setId(result.getLong("id"));
car.setName(result.getString("name"));
car.setPrice(result.getInt("price"));
return car;
};
这是结果集行到Car
对象的映射。
var car = (Car) jtm.queryForObject(sql, new Object[] {id}, rm);
RowMapper
的实例作为第三个参数传递到queryForObject()
。
BeanPropertyRowMapper
BeanPropertyRowMapper
是一种RowMapper
实现,可将行转换为指定映射目标类的新实例。 映射的目标类必须是顶级类,并且必须具有默认或无参数构造器。 结果集元数据中的列名与相应属性的公共设置器匹配。
com/zetcode/model/Car.java
package com.zetcode.model;
public class Car {
private Long id;
private String name;
private int price;
// getters and setters etc.
}
这是我们将cars
表行映射到的Car
bean。
com/zetcode/SpringBeanPropertyRowMapper.java
package com.zetcode;
import com.zetcode.model.Car;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import java.sql.SQLException;
public class SpringBeanPropertyRowMapper {
public static void main(String[] args) throws SQLException {
var dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new com.mysql.jdbc.Driver());
dataSource.setUrl("jdbc:mysql://localhost:3306/testdb");
dataSource.setUsername("user7");
dataSource.setPassword("s$cret");
var sql = "SELECT * FROM cars WHERE id=?";
Long id = 1L;
var jtm = new JdbcTemplate(dataSource);
var car = (Car) jtm.queryForObject(sql, new Object[]{id},
BeanPropertyRowMapper.newInstance(Car.class));
System.out.println(car);
}
}
该示例连接到testdb
数据库,并从cars
表中检索一辆汽车。
var sql = "SELECT * FROM cars WHERE id=?";
该 SQL 语句从数据库中选择汽车对象。
var jtm = new JdbcTemplate(dataSource);
JdbcTemplate
已创建; 它以数据源为参数。
var car = (Car) jtm.queryForObject(sql, new Object[]{id},
BeanPropertyRowMapper.newInstance(Car.class));
使用queryForObject()
方法,我们查询一个对象。 我们提供了 SQL 语句,参数和行映射器。 BeanPropertyRowMapper
将一行转换为Car
目标类的新实例。
System.out.println(car);
取回的汽车被打印到终端。
Car{id=1, name='Audi', price=52642}
应用从cars
表中打印第一行。
queryForList()
方法
queryForList()
方法执行对结果列表的查询。 在以下示例中,我们从cars
表中检索所有汽车。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ SpringDBQueryForList.java
│ └───resources
│ db.properties
└───test
└───java
这是项目结构。
我们将数据源属性放入db.properties
文件。 最好将资源与 Java 文件分开。
resources/db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.username=user7
jdbc.password=s$cret
这些是 MySQL 数据库的属性。
com/zetcode/SpringDBQueryForList.java
package com.zetcode;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Driver;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class SpringDBQueryForList {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
var prop = new Properties();
prop.load(new FileInputStream("src/main/resources/db.properties"));
var ds = new SimpleDriverDataSource();
ds.setDriverClass(((Class<Driver>) Class.forName(prop.getProperty("jdbc.driver"))));
ds.setUrl(prop.getProperty("jdbc.url"));
ds.setUsername(prop.getProperty("jdbc.username"));
ds.setPassword(prop.getProperty("jdbc.password"));
var sql = "SELECT * FROM cars";
var jtm = new JdbcTemplate(ds);
var rows = (List<Map<String, Object>>) jtm.queryForList(sql);
rows.forEach(System.out::println);
}
}
该示例连接到 MySQL testdb
数据库,并从cars
表中检索所有行。
var prop = new Properties();
prop.load(new FileInputStream("src/main/resources/db.properties"));
数据源属性是从db.properties
文件加载的。
var ds = new SimpleDriverDataSource();
ds.setDriverClass(((Class<Driver>) Class.forName(prop.getProperty("jdbc.driver"))));
ds.setUrl(prop.getProperty("jdbc.url"));
ds.setUsername(prop.getProperty("jdbc.username"));
ds.setPassword(prop.getProperty("jdbc.password"));
我们用属性填充SimpleDriverDataSource's
属性。
var jtm = new JdbcTemplate(ds);
var rows = (List<Map<String, Object>>) jtm.queryForList(sql);
JdbcTemplate
的queryForList()
方法返回表中的行列表。
rows.forEach(System.out::println);
我们遍历列表并将数据打印到终端。
{id=1, name=Audi, price=52642}
{id=2, name=Mercedes, price=57127}
{id=3, name=Skoda, price=9000}
{id=4, name=Volvo, price=29000}
{id=5, name=Bentley, price=350000}
{id=6, name=Citroen, price=21000}
{id=7, name=Hummer, price=41400}
{id=8, name=Volkswagen, price=21600}
这是示例的输出。
使用命名参数
NamedParameterJdbcTemplate
是具有一组基本 JDBC 操作的模板类,允许使用命名参数而不是传统的?
占位符。
resources/db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.username=user7
jdbc.password=s$cret
这些是 MySQL 数据库的属性。
com/zetcode/model/Car.java
package com.zetcode.model;
public class Car {
private Long id;
private String name;
private int price;
// getters and setters etc.
}
这是Car
bean。
com/zetcode/SpringDBNamedParameters.java
package com.zetcode;
import com.zetcode.model.Car;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Driver;
import java.util.Properties;
public class SpringDBNamedParameters {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
var prop = new Properties();
prop.load(new FileInputStream("src/main/resources/db.properties"));
var ds = new SimpleDriverDataSource();
ds.setDriverClass(((Class<Driver>) Class.forName(prop.getProperty("jdbc.driver"))));
ds.setUrl(prop.getProperty("jdbc.url"));
ds.setUsername(prop.getProperty("jdbc.username"));
ds.setPassword(prop.getProperty("jdbc.password"));
var sql = "SELECT * FROM cars WHERE name LIKE :name";
var carName = "Volvo";
var jtm = new NamedParameterJdbcTemplate(ds);
var namedParams = new MapSqlParameterSource("name", carName);
var car = (Car) jtm.queryForObject(sql, namedParams,
BeanPropertyRowMapper.newInstance(Car.class));
System.out.println(car);
}
}
该示例查找汽车名称; 其 SQL 代码使用命名参数。
var sql = "SELECT * FROM cars WHERE Name LIKE :name";
SQL 具有:name
令牌,这是一个命名参数。
var jtm = new NamedParameterJdbcTemplate(ds);
NamedParameterJdbcTemplate
用于命名参数。
var namedParams = new MapSqlParameterSource("name", carName);
MapSqlParameterSource
用于将参数值的简单映射传递给NamedParameterJdbcTemplate
类的方法。
var car = (Car) jtm.queryForObject(sql, namedParams,
BeanPropertyRowMapper.newInstance(Car.class));
命名的参数作为第二个参数传递给queryForObject()
方法。
Car{id=4, name='Volvo', price=29000}
这是示例的输出。
使用JdbcTemplate
的经典 Spring 示例
在下面的示例中,我们创建一个经典的命令行 Spring 应用,该应用使用JdbcTemplate
连接到数据库并发出 SQL 语句。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ ClassicSpringJdbcTemplate.java
│ │ ├───config
│ │ │ DBConfig.java
│ │ ├───model
│ │ │ Car.java
│ │ └───service
│ │ CarService.java
│ │ ICarService.java
│ └───resources
│ db.properties
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>classicspringex</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-version>5.1.3.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
</project>
Maven pom.xml
文件包含 MySQL 驱动程序,核心 Spring 库和 JdbcTemplate 的依赖项。
com/zetcode/model/Car.java
package com.zetcode.model;
public class Car {
private Long id;
private String name;
private int price;
// getters and setters etc.
}
这是Car
bean。
resources/db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb
jdbc.username=user7
jdbc.password=s$cret
这些是数据库属性。
com/zetcode/config/DBConfig.java
package com.zetcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
@PropertySource(value = "classpath:db.properties", ignoreResourceNotFound = true)
public class DBConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
var dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driver"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() {
var template = new JdbcTemplate();
template.setDataSource(dataSource());
return template;
}
}
DBConfig
生成两个 bean:dataSource
和jdbcTemplate
。 从db.properties
中读取数据库属性。
com/zetcode/service/ICarService.java
package com.zetcode.service;
import com.zetcode.model.Car;
import java.util.List;
public interface ICarService {
Car findById(Long id);
List<Car> all();
}
ICarService
定义了两种签约方法:findById()
和all()
。
com/zetcode/service/CarService.java
package com.zetcode.service;
import com.zetcode.model.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CarService implements ICarService {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Car> all() {
return jdbcTemplate.query("SELECT * FROM cars",
BeanPropertyRowMapper.newInstance(Car.class));
}
public Car findById(Long id) {
var sql = "SELECT * FROM cars WHERE id=?";
return jdbcTemplate.queryForObject(sql, new Object[]{id},
BeanPropertyRowMapper.newInstance(Car.class));
}
}
CarService
具有与JdbcTemplate
一起使用的代码。
@Autowired
private JdbcTemplate jdbcTemplate;
Spring 允许使用@Autowired
注入依赖项。 使用字段注入,我们添加了DBConfig
中生成的jdbcTemplate
bean。
com/zetcode/ClassicSpringJdbcTemplate.java
package com.zetcode;
import com.zetcode.model.Car;
import com.zetcode.service.ICarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.zetcode")
public class ClassicSpringJdbcTemplate {
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(ClassicSpringJdbcTemplate.class);
var app = ctx.getBean(ClassicSpringJdbcTemplate.class);
app.run();
ctx.close();
}
@Autowired
private ICarService carService;
private void run() {
System.out.println("Fetching a car with Id 3");
Long id = 3L;
var car = (Car) carService.findById(id);
System.out.println(car);
System.out.println("Fetching all cars");
var cars = carService.all();
cars.forEach(System.out::println);
}
}
该示例使用JdbcTemplate
从表中检索特定行和所有行。
var ctx = new AnnotationConfigApplicationContext(ClassicSpringJdbcTemplate.class);
AnnotationConfigApplicationContext
允许创建带有特定注解的 Spring bean,例如@Service
或@Configuration
。
@Autowired
private CarService carService;
数据库功能委托给CarService
,并随同@Autowired
一起注入。
private void run() {
System.out.println("Fetching a car with Id 3");
Long id = 3L;
var car = (Car) carService.findById(id);
System.out.println(car);
System.out.println("Fetching all cars");
var cars = carService.all();
cars.forEach(System.out::println);
}
我们调用服务方法来获取特定行并获取所有行。
Fetching a car with Id 3
Car{id=3, name='Skoda', price=9000}
Fetching all cars
Car{id=1, name='Audi', price=52642}
Car{id=2, name='Mercedes', price=57127}
Car{id=3, name='Skoda', price=9000}
Car{id=4, name='Volvo', price=29000}
Car{id=5, name='Bentley', price=350000}
Car{id=6, name='Citroen', price=21000}
Car{id=7, name='Hummer', price=41400}
Car{id=8, name='Volkswagen', price=21600}
这是输出。
使用JdbcTemplate
的 Spring Boot 示例
在这个例子中,我们创建一个命令行 Spring Boot 应用,它将使用JdbcTemplate
连接到数据库。 我们将有两个数据源:一个用于 Derby,一个用于 MySQL。 该项目可在作者的 Github 页面上找到。
pom.xml
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ │ MyRunner.java
│ │ ├───config
│ │ │ AppConfig.java
│ │ ├───model
│ │ │ Car.java
│ │ ├───repository
│ │ │ CarRepository.java
│ │ │ ICarRepository.java
│ │ └───service
│ │ CarService.java
│ │ ICarService.java
│ └───resources
│ application.properties
└───test
└───java
这是项目结构。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>springbootjdbctemplate</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
pom.xml
文件包含 Spring Boot 和 MySQL 的依赖项。
resources/application.properties
mysql.datasource.driverClassName=com.mysql.jdbc.Driver
mysql.datasource.jdbcUrl=jdbc:mysql://localhost:3306/testdb
mysql.datasource.username=user7
mysql.datasource.password=s$cret
在application.properties
文件中,我们定义 MySQL 数据源。
com/zetcode/config/AppConfig.java
package com.zetcode.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class AppConfig {
@Bean
@ConfigurationProperties(prefix = "mysql.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
}
在AppConfig
中,我们使用DataSourceBuilder
创建一个 MySQL 数据源。
com/zetcode/model/Car.java
package com.zetcode.model;
public class Car {
private Long id;
private String name;
private int price;
// getters and setters etc.
}
这是Car
bean。
com/zetcode/repository/ICarRepository.java
package com.zetcode.repository;
import com.zetcode.model.Car;
import java.util.List;
public interface ICarRepository {
void saveCar(Car car);
Car findCarByName(String name);
List<Car> findAll();
}
ICarRepository
包含以下方法:保存新车,以其名称取回汽车并取回所有汽车。
com/zetcode/repository/CarRepository.java
package com.zetcode.repository;
import com.zetcode.model.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class CarRepository implements ICarRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void saveCar(Car car) {
var sql = "INSERT INTO cars(name, price) VALUES (?, ?)";
Object[] params = new Object[] {car.getName(), car.getPrice()};
jdbcTemplate.update(sql, params);
}
@Override
public Car findCarByName(String name) {
var sql = "SELECT * FROM cars WHERE name = ?";
Object[] param = new Object[] {name};
return jdbcTemplate.queryForObject(sql, param,
BeanPropertyRowMapper.newInstance(Car.class));
}
@Override
public List<Car> findAll() {
var sql = "SELECT * FROM cars";
return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(Car.class));
}
}
CarRepository
包含ICarRepository
合同的实现。 这是与JdbcTemplate
一起使用的层。
com/zetcode/service/ICarService.java
package com.zetcode.service;
import com.zetcode.model.Car;
import java.util.List;
public interface ICarService {
Car findByName(String name);
List<Car> findAll();
}
我们有两种合同服务方式。
com/zetcode/service/CarService.java
package com.zetcode.service;
import com.zetcode.model.Car;
import com.zetcode.repository.ICarRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CarService implements ICarService {
@Autowired
private ICarRepository carRepository;
public Car findByName(String name) {
return carRepository.findCarByName(name);
}
public List<Car> findAll() {
return carRepository.findAll();
}
}
CarService
包含ICarService
合同的实现。 服务方法委托给ICarRepository
。
com/zetcode/MyRunner.java
package com.zetcode;
import com.zetcode.model.Car;
import com.zetcode.service.ICarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Component;
@Component
public class MyRunner implements CommandLineRunner {
@Autowired
private ICarService carService;
@Override
public void run(String... args) {
try {
var car = carService.findByName("Citroen");
System.out.println(car);
} catch (EmptyResultDataAccessException e) {
System.out.println("Car was not found");
}
var cars = carService.findAll();
for (Car car: cars) {
System.out.println(car);
}
}
}
Spring Boot 命令行应用必须实现CommandLineRunner
接口。 我们将要执行的代码放入run()
方法中。
@Autowired
private ICarService carService;
Spring 注入carService
bean。
try {
var car = carService.findByName("Citroen");
System.out.println(car);
} catch (EmptyResultDataAccessException e) {
System.out.println("Car was not found");
}
我们试图找到一辆名为雪铁龙的汽车。 如果没有这样的汽车,Spring 会抛出EmptyResultDataAccessException
异常。
var cars = carService.findAll();
for (Car car: cars) {
System.out.println(car);
}
我们使用findAll()
方法从数据库中检索所有汽车。 数据被打印到控制台。
com/zetcode/Application.java
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这是 Spring Boot 应用的入口。
在本教程中,我们介绍了 Spring 的JdbcTemplate
模块。 我们创建了一个使用JdbcTemplate
的 Spring Boot 应用。 ZetCode 具有以下相关教程: Java 教程, Spring JdbcTemplate
教程, Spring EmbeddedDatabaseBuilder
教程, EclipseLink 教程, Hibernate Derby 教程, Servlet FreeMarker JdbcTemplate
教程, MySQL Java 教程和 PostgreSQL Java 教程。