JPA映射为两个嵌套的@Embeddable问题 [英] Issue with JPA mapping for two nested @Embeddable

查看:116
本文介绍了JPA映射为两个嵌套的@Embeddable问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

接下来是数组的内容:

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

-

  org.hibernate.persister 。采集; 

public abstract class AbstractCollectionPersister
$ b $ 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]);



$ b $ / code>

映射

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

/ p>

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

  @MappedSuperclass 
public class BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =ID)
保护长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扩展BaseEntity {

@Column(name =ITEM_NAME)
私有字符串名称;

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name =ITEM_IMAGE,joinColumns = @JoinColumn(name =ITEM_ID))
private List< Image> ; images = new ArrayList< Image>();

private Item(){}
$ b $ public Item(String name,List< Image> images){
this.name = name;
this.images = images;
}

公共列表<图片> getImages(){
返回图像;
}

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;

私人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
公共类照片扩展BaseEntity {
私有字符串标题;

@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name =PHOTO_METADATA,joinColumns = @JoinColumn(name =PHOTO_ID))
private List< ImageMetadata> ;元数据列表;

private Photo(){}

public Photo(String title,List< ImageMetadata> metadataList){
this.title = title;
this.metadataList = metadataList;



解决方案

问题解决我是否添加getters / setters。不过,我仍然不明白为什么我需要这样做,为什么Photo实体映射没有访问器。
根据Java持久与Hibernate(作者是Hibernate开发人员)第二版
这是JPA中的一个规则:如果@Id在字段上,则JPA提供程序将访问类的字段直接
BaseEntity在字段上使用@Id,因此访问类型是FIELD,而不是PROPERTY。
我不明白为什么Hibernate无法在访问类型为FIELD时使用反射嵌套嵌入对象。



如果我添加@Access (AccessType.FIELD)注解到@Embeddable ImageData。



总结

根据JPA规范


2.3.1默认访问类型



默认情况下,单个访问类型(字段或属性访问)适用于实体层次结构。实体层次结构的默认访问类型取决于映射注释对实体类的属性以及未明确指定访问类型的实体层次结构的映射超类的位置。访问类型通过Access注释[6]显式指定,如2.3.2节所述

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

When Hibernate trying create mapping for the Item the next Exception throws http://pastebin.com/RdysJeiU

The cause of the exception is mismatch between column number and actual properties number.

The next is content of 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] );
        }
    }

}

The mapping of the Photo entity complete without error.

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

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

解决方案

Problem solves if I add getters/setters. However, I still don't understand why I need to do this and why for Photo entity mapping works without accessors. According to "Java Persistence with Hibernate" (authors are the Hibernate developers) second edition " This is a rule in JPA: if @Id is on a field, the JPA provider will access fields of the class directly" The BaseEntity use @Id on a field, so access type is the FIELD, not PROPERTY. I don't understand why Hibernate can't use reflection for nesting embedded object's when access type is FIELD.

The problem also solves if I add @Access(AccessType.FIELD) annotation to @Embeddable ImageData.

Summary

According to JPA specification

2.3.1 Default Access Type

By default, a single access type (field or property access) applies to an entity hierarchy. The default access type of an entity hierarchy is determined by the placement of mapping annotations on the attributes of the entity classes and mapped superclasses of the entity hierarchy that do not explicitly specify an access type. An access type is explicitly specified by means of the Access annotation [6], as described in section 2.3.2

It's not work for the nesting @Embeddable classes (more than one), if you using the Hibernate. For the proper mapping you need to explicitly specify the access type on @Embeddable classes.

这篇关于JPA映射为两个嵌套的@Embeddable问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆