Mike has posted 2 posts at DZone. View Full User Profile

Looking Forward To JPA 2.0 - Part 2

06.03.2008
| 51209 views |
  • submit to reddit
 


Mapping Models More Flexibly

There are times when the ideal object model must map to a pre-existing data model that does not fit perfectly with the mappings available in JPA 1.0. The flexibility to use alternative data models adds power and applicability to the API.


Unary Join Table


A unidirectional many-to-one or one-to-one relationship is almost always modelled by a foreign key in the primary table of the source entity. In the case of a bidirectional one-to-one it may of course be in the primary table of the target entity when looking at it from the other side of the relationship. On rare occasions a separate join table may be used to store the foreign key. As a result, it was necessary to permit designating a separate join table for this purpose and not require it to be in the table of one or the other entity. Let’s go back to our Vehicle entity and try this out.

We may have a table that links a vehicle to the individual to whom the vehicle is registered. By adding a one-to-one relationship between Vehicle and Owner, and specifying a @JoinTable annotation in addition to the @OneToOne annotation on the owner relationship, then the default join table values will apply.

Unidirectional One-to-Many Foreign Key

The most reasonable and common way to model a one-to-many/many-to-one relationship is for the relationship to be bidirectional and to store a foreign key on the many-to-one side. However, in some obscure cases, some have asked for the ability to have a unidirectional one-to-many relationship, but keep the foreign key on the many-to-one side. This would be equivalent to, say, having a one-to-many relationship from Vehicle to its parts, but not having any relationship from Part back to Vehicle, even though the foreign key column exists in the PART table. Whenever a part is added to the list of parts for a vehicle then the row corresponding to that part in the PART table must be updated, even though the Part entity knows nothing about the vehicle it is a part of.

The problem reduces to the fact that there is relationship metadata (a foreign key) being stored with Part instances, even though the Part entity does not really participate in that relationship. Nevertheless, the mapping has been added, and the join table that is normally required for unidirectional one-to-many mappings is now optional. The way to identify a mapping such as the one we are describing is to annotate the relationship with the @JoinColumn annotation. If the @JoinColumn name attribute is omitted the default join column rules will apply.

@Entity
public class Vehicle {

    @Id int vin;

    @OneToMany
    @JoinColumn(name=”V_ID”)
    Collection<Part> parts;
    …
}

The absence of the mappedBy attribute in the @OneToMany annotation indicates that the Vehicle entity owns the relationship, i.e. that it is unidirectional, and the presence of @JoinColumn indicates that the foreign key is in the target PART table and not in a join table.

Summary

You are now experts in the object-relational aspects of JPA 2.0 mappings and can impress your friends by saying things like: “I can’t wait until JPA 2.0 comes out, when I can use a collection table to store my map of basic objects keyed by embeddables.” At that point you just walk away and pretend that what you were talking about was so incredibly valuable that a person would have to be crazy not to use it.

Next time round we will look at the query enhancements and how expressions can be used in JPA to create dynamic, object-oriented queries. Stay tuned!

For further background information read part 1 of this article series.


 

Published at DZone with permission of its author, Mike Keith.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Bernhard Messerer replied on Wed, 2008/06/04 - 7:06am

So this is the JPA of the future? Anybody else diturbed by having five times as many annotations as code - it's becoming sort of an embedded language.

Couldn't find it, but when annotations came up, there was a joke about 'annotation programming', a servlet with 20 or so annotations like '@flow("if user is root then show_admin_link else show_user_link end")' ... (un)funny - whenever we discover something is 'bad' (XML-DDs) we swing completely to the opposite direction and find it equally bad (wait a few years, everybody will scream about the lots and lots of 'heavyweight'annotations unchangeable at runtime) instead of finding the middle ground.

 Messi

Geoffrey De Smet replied on Fri, 2008/06/06 - 1:09am

It feels strange to me that the @Column defines the name of a column on another table. It violates the principle of least surprise (at least to me).

I feel like a seperate annotation or property on @CollectionTable would be a lot more consistent:

@ElementCollection
@CollectionTable(name=”VEH_OPTNS”, columnName="FEAT")
Set<FeatureType> optionalFeatures;

 

Great article. Much better than those (java != dead) articles that litter the frontpage these days. How's the work on standarizing the Hibernate Criteria API going? I am really intersted to see how JPA will define that API.

Donny A. Wijaya replied on Sun, 2008/07/06 - 2:36am

Hi

I wonder if the next JPA 2.0 would include @TypeDef like in Hibernate 3? IMHO, it is a very useful feature. It will allow developers to specify custom type to allow JPA to persist the attribute transparently using the custom type (like in Jasypt and Joda-Time)

Donny

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.