Spring JdbcTemplate教程

Spring JdbcTemplate教程展示了如何使用Spring的JdbcTemplate处理数据。我们MySQL数据库。我们创建了使用 JdbcTemplate 的经典 Spring 和 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行映射器

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。它具有id 、​​​​​​​​​​​​​​nameprice属性。​​​​​​​

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实现。映射的目标类必须是顶级类,并且必须具有默认或无 arg 构造函数。结果集元数据中的列名将与相应属性的公共 setter 匹配。

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 语句从数据库中选择一个 car 对象。

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

这是项目结构。

我们将数据源属性放入文件中。最好将资源与 Java 文件分开。db.properties

resources/db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root

这些是 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属性。​​​​​​​

var jtm = new JdbcTemplate(ds);
var rows = (List<Map<String, Object>>) jtm.queryForList(sql);

JdbcTemplate's 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

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应用程序,该应用程序使用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 文件包含 MySQL 驱动程序、核心 Spring 库和 JdbcTemplate 的依赖项。pom.xml

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

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生成两个豆子:dataSourcejdbcTemplate。数据库属性从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 。使用字段注入,我们添加 jdbcTemplate在 ​​​​​​​​​​​​​​DBConfig中生成的 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>8.0.20</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>

该文件包含Spring Boot和MySQL的依赖项。pom.xml

resources/application.properties

mysql.datasource.driverClassName=com.mysql.cj.jdbc.Driver
mysql.datasource.jdbcUrl=jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC
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豆子。

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;

春天注入carService豆子。

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模块。我们创建了一个 Spring Boot 应用程序,该应用程序利用 了JdbcTemplate

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值