Я использую несколько источников данных в своем проекте, все ссылаются на один и тот же postgres на данный момент, у всех есть свои @Configuration
.
Если я запускаю простой тест, который просто вставляет один новый Созданный экземпляр моего класса сущностей, он работает нормально, если я запускаю его со следующими аннотациями
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(TelemetryDatabaseConfiguration::class)
, однако, если я запускаю его как приложение или комментирую свои тесты с помощью @SpringBootTest
, я сталкиваюсь с 2 ошибками, даже для первой записи, записанной в пустую базу данных:
- Одно поле,
ElementCollection
, полностью игнорируется: оно не является частью оператора insert
, хотя оно помечено nullable = false
(что приводит к нарушению ограничения NOT NULL
) - Если я задаю необязательную часть моих данных, которая находится в своей собственной таблице и на которую ссылается через
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
Есть идеи, как узнать, в какой конфигурации мне не хватает?