在本教程中,我们将展示如何使用 JDBI 处理数据。我们选择 MySQL 作为我们的数据库。
JDBI是一个建立在 JDBC 之上的便利库。它使数据库编程变得更加容易。它管理异常。它具有用于自动资源管理和将结果集映射到类的工具。JDBI 在概念上类似于 Spring 的JdbcTemplate。
实例通过DBI实例提供与数据库的连接Handle。 Handle表示与数据库系统的连接;它是 JDBC Connection 对象的包装器。
JDBI 提供了两种不同的风格 API:流式风格和对象风格。
在本节中,我们testdb在 MySQL 中创建一个新数据库。我们使用mysql监视器来完成这项工作,但我们也可以使用 NetBeans 数据库工具。
cars_mysql.sql
- DROP TABLE IF EXISTS Cars;
- CREATE TABLE Cars(Id INT PRIMARY KEY AUTO_INCREMENT,
- Name TEXT, Price INT) 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 testuser -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 POM 文件:
- "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.0modelVersion>
- <groupId>com.zetcodegroupId>
- <artifactId>JDBIExartifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>jarpackaging>
- <properties>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- <maven.compiler.source>1.8maven.compiler.source>
- <maven.compiler.target>1.8maven.compiler.target>
- properties>
-
- <dependencies>
- <dependency>
- <groupId>org.jdbigroupId>
- <artifactId>jdbiartifactId>
- <version>2.73version>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.39version>
- dependency>
-
- dependencies>
-
- project>
我们已经为 JDBI 库和 MySQL 驱动程序定义了依赖关系。
在以下示例中,我们将使用 JDBI Fluent API 来处理 MySQL 数据库。
在第一个示例中,我们从Cars表中获取所有汽车。
- package com.zetcode;
-
- import java.util.List;
- import java.util.Map;
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
- import org.skife.jdbi.v2.Query;
-
- public class JDBIEx {
-
- public static void main(String[] args) {
-
- Handle handle = null;
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- String sql = "SELECT * FROM Cars";
-
- try {
-
- handle = dbi.open();
- Query
- List
-
- for (Map
m : l) { -
- System.out.printf("%d ", m.get("Id"));
- System.out.printf("%s ", m.get("Name"));
- System.out.println(m.get("Price"));
- }
-
- } finally {
- if (handle != null) {
- handle.close();
- }
- }
- }
- }
该示例连接到testdb数据库并从Cars表中检索所有汽车。
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
DBI使用该类 为数据库创建一个访问点。
handle = dbi.open();
使用Handle该DBI's open()方法创建数据库。它表示与数据库的连接。与数据库的连接是使用DriverManager.
Query
使用该方法创建一个Query对象createQuery()。
List
从查询对象中,我们得到一个键/值对列表。
- for (Map
m : l) { -
- System.out.printf("%d ", m.get("Id"));
- System.out.printf("%s ", m.get("Name"));
- System.out.println(m.get("Price"));
- }
我们遍历列表并打印所有列。
- } finally {
- if (handle != null) {
- handle.close();
- }
- }
最后,我们关闭手柄。
- 1 Audi 52642
- 2 Mercedes 57127
- 3 Skoda 9000
- 4 Volvo 29000
- 5 Bentley 350000
- 6 Citroen 21000
- 7 Hummer 41400
- 8 Volkswagen 21600
这是示例的输出。
在下一个示例中,我们Cars 通过 ID 从表中获取汽车名称。
- package com.zetcode;
-
- import java.util.Map;
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
- import org.skife.jdbi.v2.Query;
- import org.skife.jdbi.v2.util.StringColumnMapper;
-
- public class JDBIEx2 {
-
- public static void main(String[] args) {
-
- Handle handle = null;
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- try {
-
- handle = dbi.open();
-
- String sql = "SELECT Name FROM Cars WHERE Id = ?";
-
- Query
- q.bind(0, 1);
-
- String carName = q.map(StringColumnMapper.INSTANCE).first();
-
- System.out.println(carName);
-
- } finally {
-
- if (handle != null) {
- handle.close();
- }
- }
- }
- }
在示例中,我们从Cars表中选择汽车名称。SQL 查询采用稍后绑定的参数。
String sql = "SELECT Name FROM Cars WHERE Id = ?";
这是用于从表中选择汽车名称的 SQL 代码。问号是稍后在代码中填写的标记。
Query
Query从 SQL 语句创建 一个新对象。
q.bind(0, 1);
使用该bind()方法,我们绑定缺少的参数。该参数是按位置绑定的。
String carName = q.map(StringColumnMapper.INSTANCE).first();
我们将结果集的一列映射StringColumnMapper 到字符串类型。该first()方法用于返回一个值。
System.out.println(carName);
汽车的名称打印在控制台上。
在此示例中,我们使用数据源连接到数据库。数据源的使用提高了应用程序的性能和可伸缩性。
- # mysql properties
- mysql.driver=com.mysql.jdbc.Driver
- mysql.url=jdbc:mysql://localhost:3306/testdb
- mysql.username=testuser
- mysql.password=test623
在db.properties文件中,我们有连接属性。

图:数据库属性
该文件被放置在项目的Resources目录中。
- package com.zetcode;
-
- import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
- import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.util.Map;
- import java.util.Properties;
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
- import org.skife.jdbi.v2.Query;
- import org.skife.jdbi.v2.util.IntegerColumnMapper;
-
- public class JDBIEx3 {
-
- public static MysqlDataSource getMySQLDataSource() throws
- FileNotFoundException, IOException {
-
- Properties props = new Properties();
- FileInputStream fis = null;
- MysqlDataSource ds = null;
-
- fis = new FileInputStream("src/main/Resources/db.properties");
- props.load(fis);
-
- ds = new MysqlConnectionPoolDataSource();
- ds.setURL(props.getProperty("mysql.url"));
- ds.setUser(props.getProperty("mysql.username"));
- ds.setPassword(props.getProperty("mysql.password"));
-
- return ds;
- }
-
- public static void main(String[] args) throws IOException {
-
- Handle handle = null;
- MysqlDataSource ds = getMySQLDataSource();
-
- DBI dbi = new DBI(ds);
-
- try {
-
- handle = dbi.open();
-
- String sql = "SELECT Price FROM Cars WHERE Id = ?";
-
- Query
- q.bind(0, 1);
-
- Integer price = q.map(IntegerColumnMapper.WRAPPER).first();
-
- System.out.println(price);
-
- } finally {
- if (handle != null) {
- handle.close();
- }
- }
- }
- }
该示例选择通过 ID 找到的汽车的价格。
- fis = new FileInputStream("src/main/Resources/db.properties");
- props.load(fis);
我们从Resources目录加载属性。
- ds = new MysqlConnectionPoolDataSource();
- ds.setURL(props.getProperty("mysql.url"));
- ds.setUser(props.getProperty("mysql.username"));
- ds.setPassword(props.getProperty("mysql.password"));
MysqlConnectionPoolDataSource已创建。我们从属性文件中设置参数。
Integer price = q.map(IntegerColumnMapper.WRAPPER).first();
由于 SQL 查询返回一个整数,因此我们使用IntegerColumnMapper该类。
该类DBI有一个名为 的便捷方法withHandle(),它管理句柄的生命周期并将其交给回调以供客户端使用。
- package com.zetcode;
-
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
- import org.skife.jdbi.v2.util.IntegerColumnMapper;
-
- public class JDBIEx4 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
- String sql = "SELECT Price FROM Cars WHERE Id = :id";
- int id = 3;
-
- Integer price = dbi.withHandle((Handle h) -> {
-
- return h.createQuery(sql)
- .map(IntegerColumnMapper.WRAPPER)
- .bind("id", id)
- .first();
- });
-
- System.out.println(price);
- }
- }
该示例选择由 ID 标识的汽车价格。
String sql = "SELECT Price FROM Cars WHERE Id = :id";
此 SQL 查询使用命名参数。
- Integer price = dbi.withHandle((Handle h) -> {
-
- return h.createQuery(sql)
- .map(IntegerColumnMapper.WRAPPER)
- .bind("id", id)
- .first();
- });
创建并执行查询,我们不必担心关闭句柄。
可以将自定义类映射到结果集。映射类必须实现ResultSetMapper接口。
- package com.zetcode;
-
- public class Car {
-
- private Long Id;
- private String Name;
- private int Price;
-
- public Car(Long Id, String Name, int Price) {
- this.Id = Id;
- this.Name = Name;
- this.Price = 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 String toString() {
- return "Car{" + "Id=" + Id + ", Name=" + Name + ", Price=" + Price + '}';
- }
- }
这是Car我们要将结果集映射到的自定义类。
- package com.zetcode;
-
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import org.skife.jdbi.v2.StatementContext;
- import org.skife.jdbi.v2.tweak.ResultSetMapper;
-
-
- public class CarMapper implements ResultSetMapper
{ -
- @Override
- public Car map(int idx, ResultSet rs, StatementContext ctx) throws SQLException {
- return new Car(rs.getLong("Id"), rs.getString("Name"), rs.getInt("Price"));
- }
- }
我们提供映射类。它返回一个Car填充了结果集中数据的新对象。
- package com.zetcode;
-
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
-
- public class JDBIEx5 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- String sql = "SELECT * FROM Cars WHERE Id = :id";
- int id = 3;
-
- Car car = dbi.withHandle((Handle h) -> {
-
- return h.createQuery(sql)
- .map(new CarMapper())
- .bind("id", id)
- .first();
- });
-
- System.out.println(car);
- }
- }
该示例Car从由其 ID 标识的表中选择一个对象。
- Car car = dbi.withHandle((Handle h) -> {
-
- return h.createQuery(sql)
- .map(new CarMapper())
- .bind("id", id)
- .first();
- });
自定义CarMapper对象被传递给该map() 方法。
批处理允许我们将相关的 SQL 语句分组到一个批处理中,并通过一次调用数据库来提交它们。这可以显着提高我们应用程序的性能。
批处理操作不是原子的;他们没有提供全有或全无的解决方案。例如,如果我们创建了不正确的 INSERT 语句,它会失败,但会执行其他 INSERT 语句。
- package com.zetcode;
-
- import org.skife.jdbi.v2.Batch;
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
-
- public class JDBIEx6 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- Handle handle = dbi.open();
- Batch batch = handle.createBatch();
-
- batch.add("DROP TABLE IF EXISTS Friends");
- batch.add("CREATE TABLE Friends(Id INT AUTO_INCREMENT PRIMARY KEY, Name TEXT)");
- batch.add("INSERT INTO Friends(Name) VALUES ('Monika')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Tom')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Jane')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Robert')");
-
- batch.execute();
- }
- }
该示例创建一个新Friends表。SQL 命令被分组为一个批处理操作。
Batch batch = handle.createBatch();
Batch代表一组未准备好的语句;它是使用该createBatch()方法创建的。
batch.add("DROP TABLE IF EXISTS Friends");
该add()方法将语句添加到批处理中。
batch.execute();
使用该execute()方法执行批处理。
事务是针对 一个或多个数据库中的数据的数据库操作的原子单元。事务中所有 SQL 语句的影响可以全部提交给数据库,也可以全部回滚。
另请注意,在 MySQL 中,DROP TABLE 和 CREATE TABLE 等 DDL 语句会导致对事务的隐式提交。
- package com.zetcode;
-
- import org.skife.jdbi.v2.Batch;
- import org.skife.jdbi.v2.DBI;
- import org.skife.jdbi.v2.Handle;
- import org.skife.jdbi.v2.TransactionStatus;
- import org.skife.jdbi.v2.VoidTransactionCallback;
-
- public class JDBIEx7 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- dbi.inTransaction(new VoidTransactionCallback() {
- @Override
- protected void execute(Handle handle, TransactionStatus status)
- throws Exception {
-
- Batch batch = handle.createBatch();
-
- batch.add("DROP TABLE IF EXISTS Friends");
- batch.add("CREATE TABLE Friends(Id INT AUTO_INCREMENT PRIMARY KEY, Name TEXT)");
- batch.add("INSERT INTO Friends(Name) VALUES ('Monika')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Tom')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Jane')");
- batch.add("INSERT INTO Friends(Name) VALUES ('Robert')");
-
- batch.execute();
- }
- });
- }
- }
该示例将批处理操作置于事务中。由于 MYSQL 中 DDL 语句的隐式提交,只有 INSERT 语句处于全有或全无模式。
- dbi.inTransaction(new VoidTransactionCallback() {
- @Override
- protected void execute(Handle handle, TransactionStatus status)
- throws Exception {
-
- ...
- }
- });
使用该inTransaction()方法创建事务。这VoidTransactionCallback 是一个不返回值的事务回调。
SQL 对象 API 为常见的 JDBI 操作提供了一种声明机制。要使用 SQL 对象 API,我们创建一个带有注释的接口或抽象类,例如@SqlQuery或@SqlUpdate。
我们创建一个示例,我们将在其中使用 SQL 对象 API 创建简单查询。
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <version>1.16.8version>
- dependency>
在示例中,我们还使用了lombok库,它减少了一些样板代码。
- package com.zetcode;
-
- import lombok.Data;
-
- @Data
- public class Car {
-
- private final Long Id;
- private final String Name;
- private final int Price;
- }
该类Car使用 lombok 的@Data 注释进行装饰。它将自动创建 getter 和 setter 方法、 equals()方法、toString()方法、 hashCode()方法和参数构造函数。
- package com.zetcode;
-
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import org.skife.jdbi.v2.StatementContext;
- import org.skife.jdbi.v2.tweak.ResultSetMapper;
-
- public class CarMapper implements ResultSetMapper
{ -
- @Override
- public Car map(int idx, ResultSet rs, StatementContext ctx) throws SQLException {
- return new Car(rs.getLong("Id"), rs.getString("Name"), rs.getInt("Price"));
- }
- }
将CarMapper结果集映射到Car类。
- package com.zetcode;
-
- import org.skife.jdbi.v2.sqlobject.Bind;
- import org.skife.jdbi.v2.sqlobject.SqlQuery;
- import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
-
- public interface MyDAO {
-
- @SqlQuery("SELECT * FROM Cars WHERE Id = :id")
- @Mapper(CarMapper.class)
- Car findById(@Bind("id") int id);
-
- @SqlQuery("SELECT COUNT(Id) FROM Cars")
- int countCars();
- }
这里我们有一个MyDAO装饰有两个 @SqlQuery注解的界面。这些方法通过 ID 查找汽车并计算表中的所有汽车。
@SqlQuery("SELECT * FROM Cars WHERE Id = :id")
@SqlQuery注解表示该方法执行指定的查询 。
@Mapper(CarMapper.class)
@Mapper指定查询方法上的结果集映射器 。
Car findById(@Bind("id") int id);
注释将@Bind方法的参数绑定到 SQL 查询参数。
- package com.zetcode;
-
- import org.skife.jdbi.v2.DBI;
-
- public class JDBIEx8 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- int id = 3;
-
- MyDAO dao = dbi.onDemand(MyDAO.class);
- Car car = dao.findById(id);
-
- System.out.println(car);
-
- int nCars = dao.countCars();
-
- System.out.printf("There are %d cars in the table", nCars);
- }
- }
在此客户端应用程序中,我们找到 ID 等于 3 的汽车,并计算表中的所有汽车。
MyDAO dao = dbi.onDemand(MyDAO.class);
该onDemand()方法创建一个新的 sql 对象,该对象将根据需要和可以分别从该 dbi 实例获取和释放连接。我们不应该显式关闭这个 sql 对象。
Car car = dao.findById(id);
我们得到一辆具有指定 ID 的汽车。
int nCars = dao.countCars();
我们计算数据库表中的汽车数量。
在 SQL Object API 中,我们可以使用@Transaction注解来创建事务。
- CREATE TABLE IF NOT EXISTS Authors(Id BIGINT PRIMARY KEY AUTO_INCREMENT,
- Name VARCHAR(25)) ENGINE=InnoDB;
-
- CREATE TABLE IF NOT EXISTS Books(Id BIGINT PRIMARY KEY AUTO_INCREMENT,
- AuthorId BIGINT, Title VARCHAR(100),
- FOREIGN KEY(AuthorId) REFERENCES Authors(Id) ON DELETE CASCADE)
- ENGINE=InnoDB;
对于此示例,我们创建两个表:Authors和Books.
- package com.zetcode;
-
- import java.util.List;
- import org.skife.jdbi.v2.exceptions.TransactionFailedException;
- import org.skife.jdbi.v2.sqlobject.Bind;
- import org.skife.jdbi.v2.sqlobject.SqlQuery;
- import org.skife.jdbi.v2.sqlobject.SqlUpdate;
- import org.skife.jdbi.v2.sqlobject.Transaction;
-
- public abstract class MyDAO {
-
- @SqlUpdate("INSERT INTO Authors(Name) VALUES(:author)")
- public abstract void createAuthor(@Bind("author") String author);
-
- @SqlQuery("SELECT Id FROM Authors WHERE Name = :name")
- abstract long getAuthorId(@Bind("name") String name);
-
- @SqlUpdate("INSERT INTO Books(AuthorId, Title) VALUES(:authorId, :title)")
- abstract void insertBook(@Bind("authorId") Long authorId, @Bind("title") String title);
-
- @Transaction
- public void insertBooksForAuthor(String author, List
titles) { -
- Long authorId = getAuthorId(author);
-
- if (authorId == null) {
- throw new TransactionFailedException("No author found");
- }
-
- for (String title : titles) {
-
- insertBook(authorId, title);
- }
- }
- }
我们有一个抽象MyDAO类,我们在其中使用@SqlUpdate、@SqlQuery和@Transaction注释。
- @SqlUpdate("INSERT INTO Authors(Name) VALUES(:author)")
- public abstract void createAuthor(@Bind("author") String author);
此方法添加了一个新作者。
- @SqlQuery("SELECT Id FROM Authors WHERE Name = :name")
- abstract long getAuthorId(@Bind("name") String name);
getAuthorId()用于获取作者的 ID 。Books当我们向表中 插入新书时,需要该 ID 。
- @SqlUpdate("INSERT INTO Books(AuthorId, Title) VALUES(:authorId, :title)")
- abstract void insertBook(@Bind("authorId") Long authorId, @Bind("title") String title);
这些insertBook()方法将一本书插入到Books 表中。
- @Transaction
- public void insertBooksForAuthor(String author, List
titles) { -
- Long authorId = getAuthorId(author);
-
- if (authorId == null) {
- throw new TransactionFailedException("No author found");
- }
-
- for (String title : titles) {
-
- insertBook(authorId, title);
- }
- }
@Transaction注释导致 在insertBooksForAuthor() 事务中运行。所以要么所有的书都被插入,要么没有。
- package com.zetcode;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import org.skife.jdbi.v2.DBI;
-
- public class JDBIEx9 {
-
- public static void main(String[] args) {
-
- DBI dbi = new DBI("jdbc:mysql://localhost:3306/testdb",
- "testuser", "test623");
-
- List
-
- Map
> autMap1 = new HashMap<>(); -
- List
books1 = new ArrayList<>(); - books1.add("Call of the Wild");
- books1.add("Martin Eden");
- books1.add("The Iron Heel");
- books1.add("White Fang");
-
- autMap1.put("Jack London", books1);
-
- Map
> autMap2 = new HashMap<>(); -
- List
books2 = new ArrayList<>(); - books2.add("Father Goriot");
- books2.add("Colonel Chabert");
- books2.add("Cousing Pons");
-
- autMap2.put("Honore de Balzac", books2);
-
- authorsBooks.add(autMap1);
- authorsBooks.add(autMap2);
-
- MyDAO dao = dbi.onDemand(MyDAO.class);
-
- for (Map
> map : authorsBooks) { -
- Set
ks = map.keySet(); -
- for (String author : ks) {
-
- dao.createAuthor(author);
-
- List
titles = map.get(author); -
- dao.insertBooksForAuthor(author, titles);
- }
- }
- }
- }
该示例将两位作者及其书籍插入数据库。
在本教程中,我们介绍了 JDBI 库。