Java Dalesbred库访问数据库

Dalesbred是一个Java库,旨在简化数据库访问过程。它通过包装JDBC提供了一种更简洁的方式来进行数据库操作,包括配置数据库连接、执行查询、更新数据等。此外,它还支持事务管理和自定义类型转换等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dalesbred 是一个致力于让 Java 更好地访问数据库的库。Dalesbred 认为 SQL 是访问数据库的好方法,但 JDBC 作为 API 会带来痛苦。因此,它使用一组帮助程序包装 JDBC,同时仍提供对低级功能的访问。

基本用法

配置数据库连接

Dalesbred 中的大多数事情都是通过Database的实例发生的。它负责管理 JDBC 连接,因此在典型应用程序中,您应该只配置一个实例——除非您需要连接多个数据库。最简单的方法是手动指定设置:

Database db = Database.forUrlAndCredentials("jdbc:example-url", "login", "password");

请注意,这不会执行连接池,因此可能不是您在生产中配置系统的首选方式。在容器中,您可能希望从 JNDI中查找命名的DataSource :

Database db = Database.forJndiDataSource("java:comp/env/jdbc/ExampleDb");

或者,您可以自己设置一个数据源,在这种情况下,您可以从中创建一个数据库

Database db = Database.forDataSource(myDataSource);

如果您使用的是Spring Framework,请参阅 Spring部分,了解如何将 Dalesbred 与其集成。

找东西

运行产生基本类型的查询很简单:

List<Integer> newIds = db.findAll(Integer.class,
    "select id from department where created_date > ?", date);

有几种方法可以获取多列的结果。首先,您可以创建一个匹配的构造函数:

List<Department> departments =
    db.findAll(Department.class, "select id, name from department");

public final class Department {
    private final int id;
    private final String name;

    @DalesbredInstantiator
    public Department(int id, String name) {
        this.id = id;
        this.name = name;
    }

    ...
}
构造函数的DalesbredInstantiator注释是可选的,但有助于 Dalesbred 在有多个构造函数时做出明确的决定。它也可用作有用的文档。最后,它可以配置为静态分析器的入口点,这样它们就不会抱怨未使用的构造函数。

除了构造函数,您还可以@DalesbredInstantiator在返回类实例的静态方法上使用。

第二个选项是使用字段或设置器绑定值。以下示例使用默认构造函数进行实例化、字段绑定 forid和 setter for name

List<Department> departments =
    db.findAll(Department.class, "select id, name from department");

...

public final class Department {
    public int id;
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

如果你有嵌套对象,你可以绑定到它们,只要路径中的所有对象都被实例化:

List<Employee> departments =
    db.findAll(Employee.class, "select id, first_name as \"name.first\", last_name as \"name.last\" from employee");

...

public final class Employee {
    public int id;
    public final Name name = new Name();
}

public final class Name {
    public String first;
    public String last;
}

您还可以将结果直接转换为地图:

Map<Integer, String> namesByIds = db.findMap(
        Integer.class, String.class, "select id, name from department");

// first column is used for key, rest for instantiating the value
Map<Integer, Department> departmentsByIds = db.findMap(
        Integer.class, Department.class, "select id, id, name from department");

如果由于某种原因您不想将结果映射到您自己的类中,您可以要求一个ResultTable,它基本上是一个ResultSet的分离表示:

ResultTable employees = db.findTable("select * from employee");

或者,您可以提供自己的RowMapper或 ResultSetProcessor -实现来代替类并手动处理结果集,但通常这应该是不必要的。

更新

正常更新很简单,因为我们不需要做太多工作来映射结果:

int modifiedRows = db.update("delete from user where id=?", 42);

如果您计划从更新中返回内容,就 Dalesbred 而言,它们是查询:

int id = db.findUniqueInt("insert into department (name) values ('foo') returning id");

查询

SqlQuery 与查询参数

所有方法都有两种变体:一个实现采用SqlQuery作为参数,另一个实现采用String和可变数量的参数。后者只是更方便的方法,这意味着以下代码片段在功能上是相同的:

import static org.dalesbred.query.SqlQuery.query;

SqlQuery query = query("select id, name from department where update_timestamp > ?", date);
db.findAll(Department.class, query);

db.findAll(Department.class,
    "select id, name from department where update_timestamp > ?", date);

通常你想使用后一种形式,但每隔一段时间,能够使用它的参数传递查询是很有用的。在这些情况下,您需要使用第一种形式。一个示例是当您动态构建查询时:

db.findAll(Department.class, buildDepartmentQuery(form));

命名查询

除了在 SQL 语句中使用位置参数之外,您还可以命名参数:

import static org.dalesbred.query.SqlQuery.namedQuery;

Map<String,Object> values = new HashMap<>();
values.put("firstName", "John");
values.put("lastName", "Doe");

db.findAll(Department.class, namedQuery("select id from employee " +
                                        " where first_name = :firstName " +
                                        "   and last_name = :lastName", values));

除了Map,您还可以将常规对象namedQuery作为值的来源传递。参数名称映射到对象的属性或字段。最后,如果你想要详细的控制,你可以通过你自己的 VariableResolver实现来解析变量。

动态构建查询

没有用于构建查询的高级 API,但QueryBuilder 可以帮助您构建动态查询。它基本上只是一个StringBuilder ,它还跟踪参数。因此,您可以这样说代码:

QueryBuilder qb = new QueryBuilder("select id, name, status from document");
if (status != null)
    qb.append(" where status=?", status);

db.findAll(Document.class, qb.build());
使用静态查询的好处是 IDEA 和 Dalesbred IDEA 插件知道如何分析它们:它们可以根据数据库模式和结果类进行验证。动态构建查询时,您将失去这些好处。如果您需要许多动态查询,请考虑在 QueryBuilder 之上构建更高级别的抽象。

交易

事务回调

要在事务中执行一堆操作,请使用TransactionCallback 或VoidTransactionCallback

db.withTransaction(tx -> {
    // transactional operations
    ...
    return result;
});

db.withVoidTransaction(tx -> {
    // transactional operations
    ...
});

或者,您还可以为这些调用传递Isolation或 Propagation

外部事务管理器

如果您使用Spring Framework,Dalesbred 可以与 Spring 的事务管理器集成。有关详细信息,请参阅Spring部分。

隐式事务

如果您在没有显式事务的情况下调用数据库,则默认情况下,每次调用都会启动一个新事务。您可以禁止这样做:在这种情况下,对于没有活动事务的调用会引发异常:

db.setAllowImplicitTransactions(false);

嵌套事务

如果您的数据库支持嵌套事务,则支持它们:

db.withTransaction(Propagation.NESTED, tx -> {
    ...
});

其他功能

显式实例化器

通常 Dalesbred 会根据数据库结果自动检测实例化类的最佳方式。这有时会导致令人惊讶的结果。如果您希望更明确,可以使用DalesbredInstantiator注释您首选的构造函数。这将导致 Dalesbred 忽略所有其他构造函数。

大型物体

只需将InputStream 或Reader传递给查询,您就可以将大对象(blob 和 clob)流式传输到数据库。同样,您可以通过询问 InputStream 或 Reader 来阅读它们。

try (InputStream in = new FileInputStream(name)) {
    db.update("insert into my_file (name, contents) values (?,?)", name, in);
}

try (InputStream in = db.findUnique(InputStream.class,
                        "select contents from my_file where name=?", name)) {
    ...
}
请注意,返回的 InputStream 或 Reader 仅在活动事务期间有效。

自定义类型转换

有时您需要将数据库值转换为您自己的自定义类型,反之亦然。为此,您可以将您的函数注册到TypeConversionRegistry

TypeConversionRegistry conversions = db.getTypeConversionRegistry();

// register conversions from database and to database types separately
conversions.registerConversionFromDatabase(
    String.class, EmailAddress.class, MyConversions::stringToEmail);
conversions.registerConversionToDatabase(
    EmailAddress.class, String.class, MyConversions::emailToString);

// or register both conversions with one call
conversions.registerConversions(
    String.class, EmailAddress.class, MyConversions::stringToEmail, MyConversions::emailToString);

集成

爪哇

Dalesbred 为以下类提供内置类型转换:

型号类型数据库类型

java.net.URI

← →

细绳

java.net.URL

← →

细绳

java.util.TimeZone

← →

细绳

短/整数/长/浮点/双

数字

大整数/大小数

数字

大整数

大十进制

字符串/java.io.Reader

克洛布

字节/java.io.InputStream

斑点

org.w3c.dom.Document

SQLXML

java.time.Instant

← →

时间戳

java.time.LocalDateTime

← →

时间戳

java.time.LocalTime

← →

时间

java.time.ZoneId

← →

细绳

java.time.LocalDate

← →

java.util.Date/java.sql.Date

科特林

Dalesbred 对Kotlin没有必需的依赖项,但带有一组扩展方法以使 Kotlin 更好用。只需从中导入所有内容org.dalesbred.integration.kotlin,您就可以开始了:

import org.dalesbred.integration.kotlin.*

...

fun findEmployees() = db.findAll<Employee>("""
      select id, name, salary
        from employee
      order by name, id
    """)

乔达时间

如果在类路径上检测到来自Joda-Time,Dalesbred 将自动注册Joda-Time的 DateTimeLocalDate 和LocalTimejava.sql.Timestamp、 java.sql.Datejava.sql.Time之间的类型转换

春天

Dalesbred 支持与Spring Framework 及其事务管理的集成。要集成 Dalesbred,请创建一个继承自 DalesbredConfigurationSupport的配置类,并为DataSource和 PlatformTransactionManager 指定 beans 。因此,最小配置将类似于以下内容:

@Configuration
@EnableTransactionManagement
public class MyDatabaseConfiguration extends DalesbredConfigurationSupport {

    @Bean
    public DataSource dataSource() {
        return new JndiDataSourceLookup().getDataSource("jdbc/my-database");
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

在此之后,您可以在 bean 中正常注入数据库。

我理解这个想法

如果您使用的是IntelliJ IDEA,请查看 Dalesbred IDEA 插件,它可以检查常见错误(例如查询参数和查询之间的不匹配)。

测试支持

通过在您的项目中包含dalesbred-junit工件作为测试依赖项,您将获得编写事务测试用例的支持:

public class MyTest {

    private final Database db =
        TestDatabaseProvider.databaseForProperties("testdb.properties");

    @Rule
    public final TransactionalTests tx = new TransactionalTests(db);

    @Test
    public void simpleTest() {
        assertEquals("hello, world!",
            db.queryForUnique(String.class "select 'hello, world!'");
    }
}

更多示例

查看dalesbred/src/test/kotlin下的测试用例 以获取更多使用示例。

下载

摇篮

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.dalesbred:dalesbred:1.3.5")
}

马文

<dependency>
    <groupId>org.dalesbred</groupId>
    <artifactId>dalesbred</artifactId>
    <version>1.3.5</version>
</dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值