R2DBC Converter,以及DatabaseClient的使用案例讲解

当使用R2DBC(Reactive Relational Database Connectivity)时,您可以使用Converter将数据库中的数据类型转换为Java对象,以便更方便地处理数据。同时,您可以使用DatabaseClient执行基于响应式流的数据库操作。以下是R2DBC Converter和DatabaseClient的具体使用案例:
继承自此webFlux基础下的R2DBC操作
R2DBC Converter简单使用案例:

假设您正在使用Spring Boot和R2DBC与数据库交互,并且有一个名为User的实体类,其中包含id(UUID类型)和name(String类型)属性。您可以使用Converter将数据库中的数据类型转换为User对象。

首先,创建一个实现Converter接口的自定义转换器:

import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;

@ReadingConverter
public class UserConverter implements Converter<Row, User> {

    @Override
    public User convert(Row row) {
        UUID id = row.get("id", UUID.class);
        String name = row.get("name", String.class);
        return new User(id, name);
    }
}

添加一个配置类,将UserConverter 配置进Bean中

@EnableR2dbcRepositories //开启 R2dbc 仓库功能;jpa
@Configuration
public class R2DbcConfiguration {
    @Bean //替换容器中原来的
    @ConditionalOnMissingBean
    public R2dbcCustomConversions conversions(){

        //把我们的转换器加入进去; 效果新增了我们的 Converter
        return R2dbcCustomConversions.of(MySqlDialect.INSTANCE,new UserConverter());
    }
}

然后,在您的数据库配置类中注册自定义转换器:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.config.R2dbcRepositoryConfigurationExtension;
import org.springframework.data.r2dbc.repository.config.R2dbcRepositoryConfigurationExtensionSupport;

@Configuration
@EnableR2dbcRepositories
public class DatabaseConfig extends AbstractR2dbcConfiguration {

    @Override
    public R2dbcCustomConversions r2dbcCustomConversions() {
        return new R2dbcCustomConversions(Collections.singletonList(new UserConverter()));
    }
}

现在,您可以在使用R2dbcRepository的地方查询User对象,并且查询结果会自动转换为User对象。

DatabaseClient使用案例:

DatabaseClient是Spring Data R2DBC中用于执行数据库操作的核心类。以下是一个简单的使用案例,演示如何使用DatabaseClient执行查询和插入操作。

首先,确保您的项目中已经添加了相关的依赖,包括spring-boot-starter-data-r2dbc

接下来,创建一个包含DatabaseClient的服务类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class UserService {
    
    private final DatabaseClient databaseClient;
    
    @Autowired
    public UserService(DatabaseClient databaseClient) {
        this.databaseClient = databaseClient;
    }
    
    public Flux<User> getAllUsers() {
        return databaseClient.select().from("users").as(User.class).fetch().all();
    }
    
    public Mono<User> getUserById(UUID id) {
        return databaseClient.select().from("users").matching(Criteria.where("id").is(id)).as(User.class).fetch().one();
    }
    
    public Mono<User> createUser(User user) {
        return databaseClient.insert().into("users").using(user).map((row, metadata) -> user).first();
    }
}

在上面的代码中,getAllUsers方法使用fetch().all()从数据库中获取所有用户。getUserById方法使用fetch().one()根据ID获取单个用户。createUser方法使用insert().using(user)将用户对象插入到数据库中,并返回插入后的用户对象。

请注意,上述代码中的User类是根据您的实际需求自定义的。
当然!以下是更多关于R2DBC Converter和DatabaseClient的使用案例:

R2DBC Converter高级使用案例:

  1. 写入数据转换器:除了读取数据之外,您还可以编写转换器将Java对象转换为数据库中的数据类型。例如,假设您希望将User对象转换为数据库行:
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;

@WritingConverter
public class UserWritingConverter implements Converter<User, Row> {

    @Override
    public Row convert(User user) {
        return DefaultRow.of(DefaultColumn.of("id", user.getId()), DefaultColumn.of("name", user.getName()));
    }
}
  1. 自定义类型转换器:如果您的实体类中包含自定义类型的属性,您可以编写自定义转换器来处理这些类型。例如,假设您的User类中有一个Address对象作为属性,您可以编写转换器将Address对象转换为数据库中的字符串类型:
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;

@WritingConverter
public class AddressWritingConverter implements Converter<Address, String> {

    @Override
    public String convert(Address address) {
        // Convert Address object to a string representation
        // For example, return address.getStreet() + ", " + address.getCity() + ", " + address.getCountry();
    }
}
  1. Converter的组合使用:如果您有多个转换器,您可以将它们组合在一起以实现复杂的数据转换逻辑。例如,您可以创建一个转换器链将数据库行转换为复杂的领域对象:
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;

@ReadingConverter
public class UserComplexConverter implements Converter<Row, User> {

    private final Converter<Row, SimpleUser> simpleUserConverter;
    private final Converter<Row, Address> addressConverter;

    public UserComplexConverter(Converter<Row, SimpleUser> simpleUserConverter, Converter<Row, Address> addressConverter) {
        this.simpleUserConverter = simpleUserConverter;
        this.addressConverter = addressConverter;
    }

    @Override
    public User convert(Row row) {
        SimpleUser simpleUser = simpleUserConverter.convert(row);
        Address address = addressConverter.convert(row);
        // Combine simpleUser and address to create a User object
    }
}

DatabaseClient高级使用案例:(可以自定义SQL)

  1. 执行更新操作:除了查询和插入操作之外,您还可以使用DatabaseClient执行更新和删除操作。例如,执行一个更新操作来更新用户的名称:
public Mono<Integer> updateUser(UUID id, String newName) {
    return databaseClient.execute("UPDATE users SET name = :name WHERE id = :id")
            .bind("name", newName)
            .bind("id", id)
            .fetch().rowsUpdated();
}
  1. 使用事务:DatabaseClient还支持事务操作。您可以使用DatabaseClient::inTransaction方法在事务中执行一系列数据库操作。例如,以下代码展示了在事务中插入多个用户的示例:
public Flux<User> createUsersInTransaction(List<User> users) {
    return databaseClient.inTransaction()
            .execute(tx -> Flux.fromIterable(users)
                    .flatMap(user -> tx.execute("INSERT INTO users (id, name) VALUES (:id, :name)")
                            .bind("id", user.getId())
                            .bind("name", user.getName())
                            .fetch().rowsUpdated()
                            .thenReturn(user)))
            .thenMany(Flux.fromIterable(users));
}

在上述代码中,createUsersInTransaction方法将用户对象列表作为输入,并在事务中将它们逐个插入数据库。事务的提交由thenMany操作完成。

  1. 处理结果集:DatabaseClient的结果集可以通过mapflatMap和其他操作进行进一步处理。例如,以下代码演示了如何将结果集转换为自定义对象列表:
public Flux<UserDetails> getUserDetails() {
    return databaseClient.select()
            .from("users")
            .matching(Criteria.where("age").isGreaterThan(18))
            .as(User.class)
            .fetch()
            .all()
            .flatMap(user -> getAdditionalDetails(user.getId())
                    .map(details -> new UserDetails(user, details)));
}

private Mono<AdditionalDetails> getAdditionalDetails(UUID userId) {
    // Perform additional query to fetch additional details based on user ID
    // Return Mono
}

上述代码中,getUserDetails方法从数据库中获取大于18岁的用户,并使用flatMap操作对每个用户调用getAdditionalDetails方法获取附加详细信息。然后,使用map操作将用户对象和附加详细信息组合成UserDetails对象。

你可能感兴趣的:(springboot,前后端技术,java,spring,boot,数据库)