ZetCode

嵌入式和客户端/服务器 JavaDB 编程

最后修改于 2020 年 7 月 13 日

在本教程中,我们将使用 JavaDB 以嵌入式和客户端/服务器模式创建 Java 应用程序。我们使用 JdbcTemplate 执行 SQL 语句。

JdbcTemplate 是一个用于简化 JDBC 编程的工具。它负责处理乏味且易出错的低级细节,例如事务处理、资源清理和正确异常处理。JdbcTemplate 包含在 Spring 的 spring-jdbc 模块中。

JavaDB

JavaDB 是随 JDK 提供的 Apache Derby 数据库。Derby 是一个用 Java 编写的关系型数据库管理系统。它实现了 SQL-92 核心子集以及一些 SQL-99 功能。它使用 IBM DB2 SQL 语法。Derby 的占地面积很小,约为 2MB。它支持事务。Derby 使用的数据库格式是可移植和平台独立的。

$ ls $JAVA_HOME/db
3RDPARTY  bin  lib  LICENSE  NOTICE  README-JDK.html  RELEASE-NOTES.html

JavaDB 的主目录位于 $JAVA_HOME/db 目录。

JDBC

JDBC 是 Java 编程语言的 API,它定义了客户端如何访问数据库。它提供了用于查询和更新数据库中数据的各种方法。JDBC 面向关系型数据库。从技术角度来看,该 API 是 java.sql 包中的一组类。要将 JDBC 用于特定数据库,我们需要该数据库的 JDBC 驱动程序。

客户端/服务器和嵌入式 Derby 应用程序

Derby 可以在 Java 应用程序中以两种基本方式使用:客户端/服务器和嵌入式。对于客户端/服务器应用程序,我们使用 org.apache.derby.jdbc.ClientDriver;对于 Derby 嵌入式应用程序,我们使用 org.apache.derby.jdbc.EmbeddedDriver

Maven 依赖

Derby 驱动程序有两个 Maven 依赖项:derbyderbynetderby 依赖项用于嵌入式应用程序,derbynet 用于客户端/服务器应用程序。

<dependency>
    <groupId>org.apache.derby</groupId>
    <artifactId>derby</artifactId>
    <version>10.13.1.1</version>
</dependency>

这是包含 derby 驱动程序的 Maven 依赖项。

<dependency>
    <groupId>org.apache.derby</groupId>
    <artifactId>derbyclient</artifactId>
    <version>10.13.1.1</version>
</dependency>

这是包含 derbyclient 驱动程序的 Maven 依赖项。

连接字符串

客户端/服务器应用程序和嵌入式应用程序的连接字符串是不同的。

jdbc:derby://:1527/dbname

这是客户端/服务器应用程序的连接 URL。

jdbc:derby:dbname

这是嵌入式应用程序的连接 URL。

CARS 表

在我们的应用程序中,我们使用以下表

cars.sql
-- SQL for the CARS table

SET SCHEMA USER12;
CREATE TABLE CARS(ID BIGINT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY 
    (START WITH 1, INCREMENT BY 1), NAME VARCHAR(30), PRICE INT);
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);

cars.sql 文件创建了 CARS 表。

$ $DERBY_HOME/bin/ij
ij version 10.11
ij> CONNECT 'jdbc:derby:testdb';
ij> RUN 'cars.sql';

使用 ij 工具,我们从 SQL 脚本创建表。

JavaDB 嵌入式应用程序

在下面的示例中,我们从 CARS 表中检索所有汽车。该应用程序以嵌入式模式使用 JavaDB。

当应用程序使用嵌入式驱动程序访问 Derby 数据库时,Derby 引擎不在单独的进程中运行,也没有需要启动和关闭的单独数据库进程。相反,Derby 数据库引擎在与应用程序相同的 Java 虚拟机 (JVM) 中运行。

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>JavaDBEmbedded</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>    
        
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.13.1.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>        
        
    </dependencies>       
    
</project>

这是 Maven POM 文件。它包含这些依赖项:derbyspring-jdbc

com/zetcode/Car.java
package com.zetcode.bean;

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;
    }
}

这是我们的 Car bean。实例化的类填充了来自 CARS 表的数据库记录。

com/zetcode/JavaDBEmbedded.java
package com.zetcode;

import com.zetcode.bean.Car;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

public class JavaDBEmbedded {
    
    public static void main(String[] args) {
        
        System.setProperty("derby.system.home", "/home/janbodnar/.derby");

        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
        dataSource.setUrl("jdbc:derby:testdb;user=USER12");

        String sql = "SELECT * FROM Cars WHERE Id=?";
        Long id = 1L;
                
        JdbcTemplate jtm = new JdbcTemplate(dataSource);
        
        Car car = (Car) jtm.queryForObject(sql, new Object[] {id}, 
                new BeanPropertyRowMapper(Car.class));        

        System.out.printf("%d ", car.getId());
        System.out.printf("%s ", car.getName());
        System.out.printf("%d ", car.getPrice());
    }
}

该示例以嵌入式模式连接到 Derby。它检索由其 ID 标识的汽车对象。

System.setProperty("derby.system.home", "/home/janbodnar/.derby");

通过设置 Derby 系统主目录,我们指示在哪里查找 testdb 数据库。

SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());

我们将 EmbeddedDriver 设置到数据源。

dataSource.setUrl("jdbc:derby:testdb;user=USER12");

这是连接到嵌入式模式下的 testdb 数据库以及 USER12 模式的 URL。

String sql = "SELECT * FROM Cars WHERE Id=?";

此 SQL 语句从数据库中选择一个汽车对象。

JdbcTemplate jtm = new JdbcTemplate(dataSource);

创建了一个 JdbcTemplate;它将数据源作为参数。

Car car = (Car) jtm.queryForObject(sql, new Object[] {id}, 
        new BeanPropertyRowMapper(Car.class));

我们使用 queryForObject 方法查询对象。我们提供了 SQL 语句、参数和行映射器。BeanPropertyRowMapper 将一行转换为 Car 目标类的新实例。

System.out.printf("%d ", car.getId());
System.out.printf("%s ", car.getName());
System.out.printf("%d ", car.getPrice());

我们将汽车数据打印到终端。

1 Audi 52642 

这是应用程序的输出。

JavaDB 客户端/服务器应用程序

在第二个示例中,我们创建了一个客户端/服务器模式的 JavaDB 应用程序。在此模式下,Derby 服务器与 Java 应用程序是分开的。

$ $DERBY_HOME/bin/startNetworkServer &

我们使用 startNetworkServer 工具启动 Derby 网络服务器。

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>JavaDBClientServer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>    
        
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.13.1.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>        
        
    </dependencies>       
    
</project>

这是 Maven POM 文件。它包含这些依赖项:derbyclientspring-jdbc

com/zetcode/Car.java
package com.zetcode.bean;

public class Car {

    private Long Id;
    private String name;
    private int price;

    // getters and setter
}

这是我们的 Car bean。

com/zetcode/JavaDBClientServer.java
package com.zetcode.main;

import com.zetcode.bean.Car;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

public class JavaDBClientServer {

    public static void main(String[] args) {

        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriver(new org.apache.derby.jdbc.ClientDriver());
        dataSource.setUrl("jdbc:derby://:1527/testdb;user=USER12");

        String sql = "SELECT * FROM Cars WHERE Id=?";
        Long id = 1L;

        JdbcTemplate jtm = new JdbcTemplate(dataSource);

        Car car = (Car) jtm.queryForObject(sql, new Object[]{id},
                new BeanPropertyRowMapper(Car.class));

        System.out.printf("%d ", car.getId());
        System.out.printf("%s ", car.getName());
        System.out.printf("%d ", car.getPrice());
    }
}

JavaDBClientServer 中,我们连接到 Derby 网络服务器并从 CARS 表检索一辆汽车。

dataSource.setDriver(new org.apache.derby.jdbc.ClientDriver());

对于客户端/服务器应用程序,我们需要 ClientDriver

dataSource.setUrl("jdbc:derby://:1527/testdb;user=USER12");

我们使用网络服务器的连接字符串。

在本教程中,我们学习了如何创建使用嵌入式和客户端/服务器模式 JavaDB 的 Java 应用程序。