question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Save with H2 in Memory not working properly

See original GitHub issue

I created a small project to setup the database with liquibase and save some data to a db with spring data r2dbc. I tested this with postgres and it works like a charm. With H2 i get an empty Mono back from spring data, even though the data is written to the db. Here is a minimal test-setup in Kotlin with Spring Boot 2.1.2.RELEASE, Spring data r2dbc 1.0.0.M1 and r2dbc Arabba-M7.

@RunWith(SpringRunner::class)
@SpringBootTest
@AutoConfigureWebTestClient
class IntegrationTest {
    private val logger = getLogger(IntegrationTest::class.java)

    @Autowired
    private lateinit var testRepo: TestRepository

    @Test
    fun `save data in h2 memory db`() {
        val testentity = Testentity(null, "Some title", "me! or I!")
        val savedEntity = testRepo.save(testentity)

        StepVerifier.create(savedEntity)
//                .expectNext(testentity.apply {id = 1}) // FIXME: I expect an entity to be returned
                .verifyComplete()

        StepVerifier.create(testRepo.findAll().collectList())
                .consumeNextWith { entityCount -> logger.debug("There are ${entityCount.count()} test entities saved")}
                .verifyComplete()
    }
}

The needed code for the application setup is as follows:

Application Context:

@SpringBootApplication
@EnableR2dbcRepositories
class DatabaseConfig: AbstractR2dbcConfiguration() {
    private val logger: Logger = getLogger(javaClass)
    private var DB_UUID: String = "testdb"

    @Bean
    override fun connectionFactory(): ConnectionFactory {
        val originDataSource = dataSource().unwrap(SimpleDriverDataSource::class.java)

        val config = ConnectionFactories.get(ConnectionFactoryOptions.builder()
                .option(ConnectionFactoryOptions.DRIVER, "h2")
                .option(ConnectionFactoryOptions.PROTOCOL, "mem")
                .option(ConnectionFactoryOptions.DATABASE, DB_UUID)
                .option(ConnectionFactoryOptions.USER, originDataSource.username!!)
                .option(ConnectionFactoryOptions.PASSWORD, originDataSource.password!!)
                .build())

        val queryFormatter = QueryExecutionInfoFormatter.showAll()

        return ProxyConnectionFactory.builder(config)
                    // Log executed query information
                    .onAfterQuery{queryExecInfo ->  queryExecInfo
                            .map(queryFormatter::format)
                            .map(logger::trace)
                            .subscribe()
                    }.build()
    }

    @Bean
    fun converter(mappingContext: RelationalMappingContext, r2dbcCustomConversions: R2dbcCustomConversions): MappingR2dbcConverter {
        return MappingR2dbcConverter(BasicRelationalConverter(mappingContext, r2dbcCustomConversions))
    }

    /**
     * Enable SQL Schema generation via Liquibase. A dataSource is needed for this
     */
    @Bean
    fun dataSource(): DataSource = EmbeddedDatabaseBuilder()
            .setName(DB_UUID)
            .setType(EmbeddedDatabaseType.H2)
            .ignoreFailedDrops(true)
            .build()
}

Entity:

@Entity
data class Testentity(
        @Id
        @GeneratedValue(strategy = AUTO)
        var id: Long?,
        @NotNull
        val title: String,
        @NotNull
        val creator: String
)

Repository:

@Repository
interface TestRepository : ReactiveCrudRepository<Testentity, Long>

Liquibase create table file:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

    <changeSet id="1" author="numbernick">
        <createTable tableName="testentity">
            <column name="id" type="BIGINT" autoIncrement="true">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="title" type="varchar(500)"/>
            <column name="creator" type="varchar(500)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>
</databaseChangeLog>

The output of the test shows that the save-methods works (it persists data), but does not return the saved data:

20-03-2019 13:06:39.346 [main] TRACE d.n.t.r.DatabaseConfig$$EnhancerBySpringCGLIB$$8f98f76c.invoke - Thread:main(1) Connection:1 Transaction:{Create:0 Rollback:0 Commit:0} Success:True Time:11 Type:Statement BatchSize:0 BindingsSize:1 Query:["INSERT INTO testentity (title, creator) VALUES($1, $2)"] Bindings:[(Some title,me! or I!)]
20-03-2019 13:06:39.366 [main] DEBUG d.n.test.reactiveh2.IntegrationTest.accept - There are 1 test entities saved
20-03-2019 13:06:39.366 [main] TRACE d.n.t.r.DatabaseConfig$$EnhancerBySpringCGLIB$$8f98f76c.invoke - Thread:main(1) Connection:2 Transaction:{Create:0 Rollback:0 Commit:0} Success:True Time:10 Type:Statement BatchSize:0 BindingsSize:0 Query:["SELECT id, title, creator FROM testentity"] Bindings:[]

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
gregturncommented, Apr 9, 2019

Looks like this is a driver-level issue. I need to inspect the flag options that can be supplied to H2, signaling to return the new key instead of row count. Given we are inside the internals of H2 (no external/internal boundary outside of JDBC APIs), this can get tricky.

0reactions
Numbernickcommented, Aug 19, 2019

For the record: This issue seems to be solved in Arabba-M8 reactiveh2-M8.zip

Read more comments on GitHub >

github_iconTop Results From Across the Web

Repository doesn't save data to H2 in-memory db
I'm going to change my db later on, just using H2 to check if my controllers work fine but it shouldn't matter here....
Read more >
H2 Database Spring Boot - How to connect and configure an ...
In this tutorial, you will learn everything you need to know to connect and configure an in- memory H2 database in Spring Boot....
Read more >
Spring Boot and H2 in memory database - in28minutes
An in memory database is created when an application starts up and destroyed when the application is stopped. Advantages. Zero project setup or ......
Read more >
Tutorial - H2 Database Engine
Open a file browser, navigate to h2/bin , and double click on h2.bat . A console window appears. If there is a problem,...
Read more >
Spring Boot With H2 Database - Baeldung
By design, the in-memory database is volatile, and results in data loss after application restart. We can change that behavior by using file- ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found