I am trying out a hexagonal architecture project and separating domain model from persistence model. But I am struggling in the case when I have to reference the foreign key of another entity in the persistence model.
I have a Customer entity that looks like this and its persistence model counterpart
class Customer(val customerId: String, val name: String) {
}
@Entity(name = "customer")
data class CustomerEntity(
var customerId: String,
var name: String,
@Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Long = -1
)
the customerId
is supposed to be the business id and the entity counterpart has additional its own database id.
Now I have another another entity Report that references the customer
class Report(val reportId: String, val date: LocalDate, val customerId: String) {
}
@Entity
data class ReportEntity(val reportId: String,
val date: LocalDate,
val customerId: String, // what should be saved here? the persistence Id (Long) of the customer or its business ID (String)?
@Id @GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = -1)
If I go with saving the persistence ID of the customer, then I would have to first fetch it from the database, which means I need to query the Customer table from within the Report component. But these two are two separate bounded contexts and I am not sure if this is the right solution or there is a modeling problem here.
I think if you don't have performance issues, you can get rid of the generated ID and use the CustomerId only.
But if you insist on having a separate ID, you will want to have the generated ID as the reference key because it's better for the performance again. On the other hand, you should consider use cases that query the Reports. Are they filtering Reports by CustomerId?
If the answer is "No", you won't have any issues because the use cases don't need the CustomerId.
But, if the answer is "Yes", then you have three options:
you can bring both IDs to the Report model. In this way, you have all the information that you need on the Report model. But be aware that the Information must be unmodifiable (like these IDs because they are not going to be updated). Because any update on this information will break your data.
you can duplicate the information of the Customer that the Report needs to know about. You must duplicate and manage it via integration events (CRUD events).
Pull data from the Customer context. In this way, you don't need to duplicate data but you will depend on Customer context.
On the first two options, you won't depend on Customer context to pull data from but they are harder to apply, especially for the second option.
The third option is easier to apply but at the cost of coupling.