nfvindaloo nfvindaloo - 13 days ago 7
Java Question

Assigning a @CollectionId to and @ElementCollection

I have a class which im trying to implement, (similar to the example in 'Java Persistence with Hibernate' 6.3.3)

public class Property
{
...

@ElementCollection(fetch=FetchType.EAGER)
@CollectionId(
columns=@Column(name="Property_image_id"),
type=@Type(type="long"),
generator="native"
)
private Collection<FileAttachment> images = new ArrayList<FileAttachment>();

...
}


The unit test fails throwing the following exception:

java.lang.ClassCastException: org.hibernate.id.IdentifierGeneratorHelper$2
cannot be cast to java.lang.Long


Im not too sure about the best value for 'generator', and I assume this will affect the outcome.

Also when i get this working, can the FileAttachment object access the Property_image_id? And how do you assign it to a property, since its defined in the Property class?

What I'd like is for the Property_images table to have a composite key [Property_id-Image_index], where Image_index starts at 1 for each new Property_id but I have no idea how to implement this using @ElementCollection and @CollectionId with a generator. Maybe i have to have FileAttachment as an @Entity instead of @Embeddable, but id rather not as its only used inside the Property class.

Cheers!
NFV

Answer

From Java Java Persistence Wikibook:

The JPA 2.0 specification does not provide a way to define the Id in the Embeddable. However, to delete or update a element of the ElementCollection mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from the CollectionTable for the Entity, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in the Embeddable are unique, in combination with the foreign key (JoinColumn(s)). This however could be inefficient, or just not feasible if the Embeddable is big, or complex. Some JPA providers may allow the Id to be specified in the Embeddable, to resolve this issue. Note in this case the Id only needs to be unique for the collection, not the table, as the foreign key is included. Some may also allow the unique option on the CollectionTable to be used for this. Otherwise, if your Embeddable is complex, you may consider making it an Entity and use a OneToMany instead.

I think that your IMAGE_INDEX requirement can be tackled with OrderColumns:

@ElementCollection(fetch=FetchType.EAGER)
@OrderColumn(name = "IMAGE_INDEX")
private List<FileAttachment> images;

This post may be useful.