4

当 Hibernate 尝试为 Item 创建映射时,下一个异常抛出http://pastebin.com/RdysJeiU

异常的原因是列号和实际属性号不匹配。

接下来是数组的内容:

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] );
        }
    }

}

Photo 实体的映射完整无误。

为什么Hibernate不能映射Item实体的@Embeddable集合属性的@Embeddable Image类的imageMetadata属性?

包model.dao.mappings;导入 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

1 回答 1

6

如果我添加 getter/setter,问题就解决了。但是,我仍然不明白为什么我需要这样做以及为什么 Photo 实体映射在没有访问器的情况下工作。根据“Java Persistence with Hibernate”(作者是 Hibernate 开发人员)第二版“这是 JPA 中的一条规则:如果 @Id 在一个字段上,JPA 提供者将直接访问该类的字段” BaseEntity 使用 @Id on一个字段,所以访问类型是字段,而不是属性。我不明白为什么当访问类型为 FIELD 时,Hibernate 不能使用反射来嵌套嵌入对象。

如果我将@Access(AccessType.FIELD) 注释添加到@Embeddable ImageData,问题也会得到解决。

概括

根据 JPA 规范

2.3.1 默认访问类型

默认情况下,单一访问类型(字段或属性访问)适用于实体层次结构。实体层次结构的默认访问类型由实体类的属性和实体层次结构的映射超类的属性上的映射注释的放置确定,这些实体层次结构没有明确指定访问类型。访问类型通过访问注释 [6] 明确指定,如第 2.3.2 节所述

如果您使用 Hibernate,它不适用于嵌套的 @Embeddable 类(多个)。对于正确的映射,您需要明确指定 @Embeddable 类的访问类型。

于 2013-08-26T12:51:46.867 回答