Reputation: 14003
This is a followup question to Hibernate: Where do insertable = false, updatable = false belong in composite primary key constellations involving foreign keys?:
Consider the following entity mapping:
public class Zip {
@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code")
private Country country = null
@Column(name = "country_code")
private String countryCode;
...
}
Like this a JPA implementation will choke saying something like "duplicate mapping for country_code, only one of them may be specified as writable".
Q:
Why is making the relationship read-only (private Country country
) preferred here/generally over putting the read-only on the simple ID field (private String countryCode
)?
Why is the one better than the other in practice (pros/cons)?
The only things I can think of is that working with writable relationships is better when the DB is not using any FKs, which would make working with entities somewhat mandatory, however, this would not prevent users from being able to insert new entities into the DB with unknown IDs, which would just make writable relationships slightly safer. Being able to work with the IDs of course would make loading the complete entities from the DB redundant, which can be a big performance aspect.
More arguments welcome.
PS: I added the JPA implementations as tags to attract more audience.
Upvotes: 1
Views: 311
Reputation: 21145
First, there is no real need for having the countryCode
mapping, as the data within it is held in the referenced country, within the mapping for the iso_code
. EclipseLink for instance can use zip.country.id = :isoCode
in a query and know it can just use the country_code
foreign key directly without having to join the tables, the same as if you used zip.countryCode = :isoCode
. So if you have both, you should have a reason for it and that reason should dictate which you want to have control the country_code
foreign key.
Second, having a relationship is not going to help you any if the database doesn't have foreign key constraints. Without constraints, if you remove the country from the database, your Zip
will still reference that country. If it isn't in the cache, then the countryCode
will have a value but the reference will be null (or throw an error depending on the provider).
I also do not agree that a relationship should be read-only; I believe it is likely done so that the relationship can be changed in the database without having to read in the referenced object which IMO is a bad practice. JPA allows 2 layers of caching, so changes will cause the cached relationship to be out of synch with the database, then require extra overhead to resolve. If you are going to do this, you might as well not map the country
relationship reference at all - read it from JPA if/when needed and store it in the entity as a transient if it makes sense.
In the end, your object model should map your business needs. Just because the database has references and fields, doesn't mean your Java entities must also map them all the exact same way.
Upvotes: 2