In a kotlin spring-boot application using JPA I currently have two entities that have a technical auto-generated id.
The entities do not have a relation to each other (for example @OneToMany annotation), yet. However they are related by non-technical attributes in the business logic.
In the given example DataEntity is connected to NameEntity over the attributes component, name, source. There can be multiple DataEntities for the same NameEntity.
(Due to step-by-step data migration reasons it was not possible in the past to work with relations in the first place.)
Question:
It is possible to reference the given entity structure by foreign key constraints? If so, how?
Ideally, I don’t want to change the DB structure.
I want to ensure data consistency with JPA/DB cascade rules, i.e. I want to delete all Data when the appropriate Name connected by the 3 attributes is deleted. (And I don’t want to code such consistency rules in the application code, of course)
@Entity
@Table(
name = "names",
uniqueConstraints = [UniqueConstraint(columnNames = ["component", "name", "source"])],
)
class NameEntity(
@Id
@GeneratedValue
var id: Long? = null,
@Version
var version: Long? = null,
@Column(name = "component")
var component: String,
@Column(name = "name")
var name: String,
@Column(name = "source")
@Enumerated(EnumType.STRING)
var source: @NotNull Source,
// below more attributes not relevant for the example...
@Column(name = "secret")
var isSecret: Boolean,
// ...
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is NameEntity) return false
return Objects.equals(id, other.id)
}
override fun hashCode(): Int = Objects.hash(id)
}
@Entity
@Table(
name = "data",
uniqueConstraints = [
UniqueConstraint(
columnNames = [
"component",
"name",
"version",
"source",
],
),
],
)
class DataEntity(
@Id
@GeneratedValue
var id: Long? = null,
@Version
var version: Long? = null,
@Column(name = "component")
var component: String,
@Column(name = "name")
var name: String,
@Column(name = "version")
var version: Int,
@Column(name = "source")
@Enumerated(EnumType.STRING)
var source: @NotNull Source,
// ...
I tried to find a suitable jakarta.persistece annotation. Something like:
class DataEntity (
//...
@ManyToOne
@JoinColumns(
value = [
JoinColumn(name = "component", referencedColumnName = "component", insertable = false, updatable = false),
JoinColumn(name = "name", referencedColumnName = "name", insertable = false, updatable = false),
JoinColumn(name = "source", referencedColumnName = "source", insertable = false, updatable = false),
]
)
@jakarta.persistence.Transient
var nameEntity: NameEntity? = null
)
I tried to use @Transient to mitigate any db changes (id column to reference NameEntity).
However, nothing is loaded from JPA.
And I am not even sure if this approach would work when I don’t have an id column to reference the NameEntity.