当前位置: 首页 > 知识库问答 >
问题:

Spring R2DBC使用postgres初始化数据库的正确方法

徐新荣
2023-03-14

我有以下代码:

@Component
public class TemplateDatabaseLoader {
    private Logger LOGGER = LoggerFactory.getLogger(TemplateDatabaseLoader.class);

    @Bean
    public CommandLineRunner demo(DatabaseClient databaseClient, ItemRepository itemRepository) {
        return args -> {
            databaseClient.execute(
                    "CREATE TABLE item (" +
                            "id SERIAL PRIMARY KEY," +
                            "name VARCHAR(255)," +
                            "price REAL" +
                        ");"
            ).fetch().all().blockLast(Duration.ofSeconds(10));
            itemRepository.save(new Item("Alf alarm clock", 19.99)).block();
            LOGGER.debug("COMMAND LINE RUNNER");
            itemRepository.save(new Item("Smurf TV tray", 24.99)).block();
        };
    }
}

以及:

@SpringBootApplication
public class DemoApplication extends AbstractR2dbcConfiguration {

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

    @Bean
    public ConnectionFactory connectionFactory() {
        PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
                .host("127.0.0.1")
                .database("cart")
                .username("cart")
                .password("cart").build());
        return connectionFactory;
    }

    @Bean(name={"r2dbcDatabaseClient"})
    DatabaseClient databaseClient() {
        return DatabaseClient.create(connectionFactory());
    }
}

我得到以下错误:

Suppressed: java.lang.Exception: #block terminated with an error
Caused by: io.r2dbc.postgresql.ExceptionFactory$PostgresqlBadGrammarException: relation "item" already exists

以及更早的错误:

Caused by: java.lang.ClassNotFoundException: org.springframework.jdbc.CannotGetJdbcConnectionException

如果我将代码修改为:

CREATE TABLE IF NOT EXISTS item

然后,我不再得到关于项目关系存在的错误,但是,似乎事务被完全取消了?

我得到以下输出:

2020-09-21 17:31:58.476 DEBUG 16639 --- [  restartedMain] com.example.demo.TemplateDatabaseLoader  : COMMAND LINE RUNNER
2020-09-21 17:31:58.476 DEBUG 16639 --- [actor-tcp-nio-2] i.r.postgresql.util.FluxDiscardOnCancel  : received cancel signal

所以我的问题是

>

  • 正确的方法是什么?

    为什么我的CommandLineRunner代码似乎执行了两次?该表在运行代码后不会持久化,因此它似乎必须执行两次才能获得关于现有表的第一个错误。

    谢谢你。

  • 共有1个答案

    娄德运
    2023-03-14

    我成功了。我添加了一个新类以从文件加载架构:

    @Configuration
    public class InitializerConfiguration {
        private Logger LOGGER = LoggerFactory.getLogger(InitializerConfiguration.class);
    
        @Bean
        public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
    
            ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
            initializer.setConnectionFactory(connectionFactory);
    
            CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
            populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
            initializer.setDatabasePopulator(populator);
    
            return initializer;
        }
    }
    

    这将加载架构。资源下的sql。我的TemplateDatabaseLoader现在如下所示:

    @Component
    public class TemplateDatabaseLoader {
        private Logger LOGGER = LoggerFactory.getLogger(TemplateDatabaseLoader.class);
    
        @Bean
        public CommandLineRunner demo(ItemRepository itemRepository) {
            return args -> {
                itemRepository.save(new Item("Alf alarm clock", 19.99)).block();
                itemRepository.save(new Item("Smurf TV tray", 24.99)).block();
            };
        }
    }
    

    这将加载这两个项目。

     类似资料:
    • 问题内容: 用RefluxJS异步初始化数据的正确方法是什么?是否有类似于AngularJS的解决方案,或者Flux的实现与此无关(路由器应该处理此职责)? 问题答案: 在应用程序的顶级组件中,使用方法(docs)触发获取数据的操作。最初渲染组件时将调用此方法。 例如:

    • 问题内容: 初始化有序词典(OD)以便保留初始数据顺序的正确方法是什么? 题: 在初始化时是否会保留元组列表的顺序,元组的元组或列表的元组或列表的列表等的顺序(上述第二和第三示例)? 如何验证是否实际维持订单?由于a具有不可预测的顺序,如果我的测试向量幸运地具有与dict不可预测的顺序相同的初始顺序,该怎么办?例如,如果不是我写,我会错误地得出结论认为该顺序已保留。在这种情况下,我发现a是按字母顺

    • 本文向大家介绍SpringBoot使用flyway初始化数据库,包括了SpringBoot使用flyway初始化数据库的使用技巧和注意事项,需要的朋友参考一下 概述 Flyway这款数据库版本工具就算大家没有使用过但也略有耳闻了,SpringBoot对该款工具进行集成的框架可以让我们在启动SpringBoot应用时自动去找SQL版本文件进行比对执行,但在迁移或初始化时往往还是需要先手动进行下数据库

    • 问题内容: 要声明一个具有固定大小的空切片,最好这样做: 要么: 只想知道哪种方法是正确的。 问题答案: 您提供的两个选择在语义上是相同的,但是使用会导致内部调用 runtime.makeslice (Go 1.14)。 您还可以选择保留其值: 如Golang.org博客中所述: nil切片在功能上等效于零长度切片,即使它没有指向任何内容。它的长度为零,可以附加分配。 甲片段将然而入而空片将编组成

    • 要声明大小不固定的空切片,最好执行以下操作: 或: 只是想知道哪一个是正确的方法。

    • 我有不使用Flyway的现有数据库postgres,我需要复制它。如何将现有数据库状态移动到新的空数据库?我没有任何迁移sql。所以我期待像Liquibase中的GenerateChangelog这样的命令,但在Flyway中似乎没有这样的命令。