JPA mapping issue for two nested @Embeddable

When Hibernate tries to create a mapping for an element, the following Exception throws http://pastebin.com/RdysJeiU

The reason for the exception is the mismatch between the column number and the actual property number.

The following is the contents of the arrays:

columnAliases = [IMAGE_TITLE] propertyNames = [imageMetadata,title] 

-

 org.hibernate.persister.collection; public abstract class AbstractCollectionPersister private void initCollectionPropertyMap(String aliasName, Type type, String[] columnAliases, String[] columnNames) { collectionPropertyColumnAliases.put( aliasName, columnAliases ); collectionPropertyColumnNames.put( aliasName, columnNames ); if ( type.isComponentType() ) { CompositeType ct = (CompositeType) type; String[] propertyNames = ct.getPropertyNames(); for ( int i = 0; i < propertyNames.length; i++ ) { String name = propertyNames[i]; collectionPropertyColumnAliases.put( aliasName + "." + name, columnAliases[i] ); collectionPropertyColumnNames.put( aliasName + "." + name, columnNames[i] ); } } } 

Display of the photo object completed without errors.

Why can't Hibernate map the imageMetadata property of the @Embeddable Image class of the @Embeddable collection property to the Item object?

package model.dao.mappings; import javax.persistence. *;

 @MappedSuperclass public class BaseEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") protected long id; public BaseEntity() {} public long getId() { return id; } } 

 package model.dao.mappings.collections.embedable; import model.dao.mappings.BaseEntity; import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity public class Item extends BaseEntity { @Column(name = "ITEM_NAME") private String name; @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID")) private List<Image> images = new ArrayList<Image>(); private Item() {} public Item(String name, List<Image> images) { this.name = name; this.images = images; } public List<Image> getImages() { return images; } public void setImages(List<Image> images) { this.images = images; } } 

 package model.dao.mappings.collections.embedable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class Image { @Column(name = "IMAGE_TITLE") private String title; private ImageMetadata imageMetadata; private Image() {} public Image(String title, ImageMetadata imageMetadata) { this.title = title; this.imageMetadata = imageMetadata; } } 

 package model.dao.mappings.collections.embedable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class ImageMetadata { @Column(name = "SIZE_X") private int sizeX; @Column(name = "SIZE_Y") private int sizeY; private ImageMetadata() {} public ImageMetadata(int sizeX, int sizeY) { this.sizeX = sizeX; this.sizeY = sizeY; } } 

 package model.dao.mappings.collections.embedable; import model.dao.mappings.BaseEntity; import javax.persistence.*; import java.util.List; @Entity public class Photo extends BaseEntity { private String title; @ElementCollection(fetch = FetchType.EAGER) @CollectionTable(name = "PHOTO_METADATA", joinColumns = @JoinColumn(name = "PHOTO_ID")) private List<ImageMetadata> metadataList; private Photo() {} public Photo(String title, List<ImageMetadata> metadataList) { this.title = title; this.metadataList = metadataList; } } 
+4
source share
1 answer

The problem is solved if I add getters / setters. However, I still do not understand why I need this, and why Phot works without accessories to map objects. According to "Java Persistence with Hibernate" (Hibernate authors), second edition "This is a rule in JPA: if @Id is in a field, the JPA provider will directly access the fields of the class" BaseEntity uses @Id in the field, so the access type is FIELD , not PROPERTY. I do not understand why Hibernate cannot use reflection for nesting an embedded object when the access type is FIELD.

The problem is also resolved by adding @Access (AccessType.FIELD) annotation to @Embeddable ImageData.

Summary

According to JPA specification

2.3.1 Default Access Type

By default, a single type of access is used for an object hierarchy (access to a field or properties). The default access type for an entity hierarchy is determined by the placement of annotations for matching attribute classes of entity classes and associated superclasses of the object hierarchy that do not explicitly indicate the type of access. The type of access is explicitly indicated using the Access annotation [6], as described in section 2.3.2

It does not work for @Embeddable nested classes (more than one) if you use Hibernate. For proper mapping, you need to explicitly specify the type of access in the @Embeddable classes.

+5
source

Source: https://habr.com/ru/post/1498925/


All Articles