Неправильное поведение JPA с SpringBootTest, исправить с помощью DataJpaTest - PullRequest
0 голосов
/ 23 апреля 2020

Я использую несколько источников данных в своем проекте, все ссылаются на один и тот же postgres на данный момент, у всех есть свои @Configuration.

Если я запускаю простой тест, который просто вставляет один новый Созданный экземпляр моего класса сущностей, он работает нормально, если я запускаю его со следующими аннотациями

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(TelemetryDatabaseConfiguration::class)

, однако, если я запускаю его как приложение или комментирую свои тесты с помощью @SpringBootTest, я сталкиваюсь с 2 ошибками, даже для первой записи, записанной в пустую базу данных:

  1. Одно поле, ElementCollection, полностью игнорируется: оно не является частью оператора insert, хотя оно помечено nullable = false (что приводит к нарушению ограничения NOT NULL)
  2. Если я задаю необязательную часть моих данных, которая находится в своей собственной таблице и на которую ссылается через OneToOne, дополнительная сторона вставляется первой, в результате чего получается Нарушение ограничения внешнего ключа.

Все @Configuration s придерживаются следующего шаблона (только что заменили «context» соответствующим именем):

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "contextEntityManagerFactory",
    transactionManagerRef = "contextTransactionManager",
    basePackages = ["my.backend.context.repo"]
)
class ContextDatabaseConfiguration {
    @Bean(name = ["contextDataSourceProperties"])
    @ConfigurationProperties("context.datasource")
    fun dataSourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean(name = ["contextDataSource"])
    @ConfigurationProperties("context.datasource.configuration")
    fun dataSource(@Qualifier("contextDataSourceProperties") dataSourceProperties: DataSourceProperties): DataSource {
        return dataSourceProperties.initializeDataSourceBuilder()
            .type(HikariDataSource::class.java).build()
    }

    @Bean(name = ["contextEntityManagerFactory"])
    fun entityManagerFactory(
        builder: EntityManagerFactoryBuilder,
        @Qualifier("contextDataSource") dataSource: DataSource
    ): LocalContainerEntityManagerFactoryBean? {
        return builder
            .dataSource(dataSource)
            .packages(ContextRecord::class.java)
            .build()
    }

    @Bean(name = ["contextTransactionManager"])
    fun transactionManager(
        @Qualifier("contextEntityManagerFactory") memberEntityManagerFactory: LocalContainerEntityManagerFactoryBean
    ): PlatformTransactionManager {
        return JpaTransactionManager(memberEntityManagerFactory.getObject()!!)
    }
}

Объекты выглядят так

@Embeddable
data class ContextId(
    @Column(name = "part_id", nullable = false) var partId: String,
    @Column(name = "recorded_at", nullable = false) var recordedAt: ZonedDateTime
) : Serializable

@Entity
@Table(name = "context_records", schema = "context")
class ContextRecord(
    @EmbeddedId
    // JvmField prevents generation of getter
    // That is necessary because the Persistable interface contains a method with the same signature
    // which results in a "Platform declaration clash"
    @JvmField
    var id: ContextId,

    @Column(name = "some_value_1", nullable = false)
    var someValue1: Short,
    @Column(name = "some_value_2", nullable = false)
    var someValue2: Short,

    @ElementCollection
    @Column(name = "value_list", insertable = true, nullable = false)
    var valueList: List<Short>,

    @OneToOne(cascade = [CascadeType.ALL])
    @JoinColumns(
        JoinColumn(name = "part_id"),
        JoinColumn(name = "recorded_at")
    )
    var contextOptional: ContextOptionalData?
)

@Entity
@Table(name = "context_optional_data", schema = "context")
data class ContextOptionalData(
    @EmbeddedId
    @JvmField
    var id: ContextOptionalDataId,

    @Column(name = "some_data_string", nullable = false)
    var some_data: String

)

И мое application.conf

context.datasource.url=jdbc:postgresql://...
context.datasource.username=...
context.datasource.password=...
context.datasource.driverClassName=org.postgresql.Driver

Есть идеи, как узнать, в какой конфигурации мне не хватает?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...