通过Reactive的方式访问RDBMS

Spring Data R2DBC

英文全部为Reactive Relational Database Connectivity
反应式关系数据库连接

这个项目并不是一个完成的项目,目前处于孵化阶段。所以支持的数据库较少。

支持的数据库

  • Postgres(io.r2dbc:r2dbc-postgresql)

  • H2(io.r2dbc:r2dbc-h2)

  • Microsoft SQL Server(io.r2dbc:r2dbc-mssql)

并不支持主流的MySql等关系型数据库
不管用拿一个都要使用相关依赖。

一些主要的类

  • ConnectionFactory
    重写这个类,定义连接
  • DatabaseClient
    通过DatabaseClient执行sql操作,调用里面的方法
    • execute().sql(SQL) 自己手动输入SQL语句
    • select( )/insert( ) 输入表名查找
    • inTransaction(db -> {}) 如果有事务的要求,把后面的操作包裹起来
  • R2dbcExceptionTranslato 处理异常r
    • SqlErrorCodeR2dbcExceptionTranslator

具体使用如下:


/**
 * @Author: 13679
 * @CreateTime: 2019-12-02 21:39
 */
@Slf4j
@SpringBootApplication
public class R2dbcDemoTest extends AbstractR2dbcConfiguration implements ApplicationRunner {
    @Autowired
    private DatabaseClient client; //注入一个数据库客户端

    public static void main(String[] args) {
        SpringApplication.run(R2dbcDemoTest.class,args);
    }

    @Bean
    public ConnectionFactory connectionFactory() {
        return new H2ConnectionFactory(
                H2ConnectionConfiguration.builder()  //使用h2的连接工厂创建一个连接,inMemory为内存数据库的名字,
                        .inMemory("testdb")
                        .username("sa")
                        .build()
        );
    }

    @Bean  //@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
    public R2dbcCustomConversions r2dbcCustomConversions(){  //覆盖掉r2dbcCustomConversions,本来里面list是空的
        Dialect dialect = getDialect(connectionFactory());
        CustomConversions.StoreConversions storeConversions=
                CustomConversions.StoreConversions.of(dialect.getSimpleTypeHolder());
        return new R2dbcCustomConversions(storeConversions,
                Arrays.asList(new MoneyReadConverter(),new MoneyWriteConverter()));
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        CountDownLatch count = new CountDownLatch(2);
        client.execute()
                .sql("select * from t_coffee")
                .as(Coffee.class)
                //将查出来的数据转化为coffee对象
                .fetch()
                //将整个结果集取出
                .first()
                //取出第一个
                .doFinally(c->count.countDown())
                .subscribeOn(Schedulers.elastic())
                .subscribe(c->log.info("Fetch execute {}",c));

        client.select()
                .from("t_coffee")
                .orderBy(Sort.by(Sort.Direction.DESC,"id"))
                //根据id 降序排序
                .page(PageRequest.of(0,3))
                .as(Coffee.class)
                .fetch()
                .all()
                .doFinally(c->count.countDown())
                .subscribeOn(Schedulers.elastic())
                .subscribe(c -> log.info("Fetch execute {}", c));
        log.info("After Starting ...");
        count.await();
    }
}

结果如下:
在这里插入图片描述

R2DBC Repository 支持

一些主要的类

  • @EnableR2dbcRepositories
    开启Repositories支持
  • ReactiveCrudRepository<T(实例), ID(类型)>

• @Table / @Id
Table :使用的哪个表
Id:哪个属性是它的id
• 其中的方法返回都是 Mono 或者 Flux
• 自定义查询需要自己写 @Query

具体代码:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table("t_coffee") //使用的表
public class Coffee {
    @Id
    private Long id;
    private String name;
    private Money price;
    private Date createTime;
    private Date updateTime;
}


public interface CoffeeRepository extends ReactiveCrudRepository<Coffee, Long> {
    @Query("select * from t_coffee where name = $1")
    Flux<Coffee> findByName(String name);
}


@SpringBootApplication
@Slf4j
@EnableR2dbcRepositories
public class R2dbcRepositoryDemoApplication extends AbstractR2dbcConfiguration
		implements ApplicationRunner {
	@Autowired
	private CoffeeRepository repository;

	public static void main(String[] args) {
		SpringApplication.run(R2dbcRepositoryDemoApplication.class, args);
	}

	@Bean
	public ConnectionFactory connectionFactory() {
		return new H2ConnectionFactory(
				H2ConnectionConfiguration.builder()
						.inMemory("testdb")
						.username("sa")
						.build());
	}

	@Bean
	public R2dbcCustomConversions r2dbcCustomConversions() {
		Dialect dialect = getDialect(connectionFactory());
		CustomConversions.StoreConversions storeConversions =
				CustomConversions.StoreConversions.of(dialect.getSimpleTypeHolder());
		return new R2dbcCustomConversions(storeConversions,
				Arrays.asList(new MoneyReadConverter(), new MoneyWriteConverter()));
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		CountDownLatch cdl = new CountDownLatch(2);

		repository.findAllById(Flux.just(1L, 2L))
				//使用默认的findAllById  输入两个id 1和2
				.map(c -> c.getName() + "-" + c.getPrice().toString())
				//使用map输出咖啡
				.doFinally(s -> cdl.countDown())
				.subscribe(c -> log.info("Find {}", c));

		repository.findByName("mocha")
				.doFinally(s -> cdl.countDown())
				.subscribe(c -> log.info("Find {}", c));

		cdl.await();
	}
}

converter层是一样

结果如下:
在这里插入图片描述

发布了59 篇原创文章 · 获赞 6 · 访问量 962

猜你喜欢

转载自blog.csdn.net/weixin_43790623/article/details/103358725