当使用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高级使用案例:
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()));
}
}
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();
}
}
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)
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();
}
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
操作完成。
map
、flatMap
和其他操作进行进一步处理。例如,以下代码演示了如何将结果集转换为自定义对象列表: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<AdditionalDetails>
}
上述代码中,getUserDetails
方法从数据库中获取大于18岁的用户,并使用flatMap
操作对每个用户调用getAdditionalDetails
方法获取附加详细信息。然后,使用map
操作将用户对象和附加详细信息组合成UserDetails
对象。