当前位置:  开发笔记 > 编程语言 > 正文

JPA Multiple Embedded字段

如何解决《JPAMultipleEmbedded字段》经验,为你挑选了3个好方法。

JPA实体类是否可以包含两个嵌入(@Embedded)字段?一个例子是:

@Entity
public class Person {
    @Embedded
    public Address home;

    @Embedded
    public Address work;
}

public class Address {
    public String street;
    ...
}

在这种情况下,一个Person可以包含两个Address实例 - 家庭和工作.我正在使用JPA和Hibernate的实现.当我使用Hibernate Tools生成模式时,它只嵌入一个Address.我想要的是两个嵌入式Address实例,每个实例的列名都有区别或预先设置了一些前缀(例如家庭和工作).我知道@AttributeOverrides,但这要求每个属性都被单独覆盖.如果嵌入的object(Address)变大,因为每个列需要单独重写,这会很麻烦.



1> Philihp Busb..:

通用的JPA方法是使用@AttributeOverride.这应该在EclipseLink和Hibernate中都有效.

@Entity 
public class Person {
  @AttributeOverrides({
    @AttributeOverride(name="street",column=@Column(name="homeStreet")),
    ...
  })
  @Embedded public Address home;

  @AttributeOverrides({
    @AttributeOverride(name="street",column=@Column(name="workStreet")),
    ...
  })
  @Embedded public Address work;
  }

  @Embeddable public class Address {
    @Basic public String street;
    ...
  }
}


请注意,`name ="street"`是指属性的名称,而不是列名.

2> Loki..:

如果要在同一实体中两次使用相同的可嵌入对象类型,则列名默认将不起作用:至少有一列必须是显式的.Hibernate超越了EJB3规范,允许您通过NamingStrategy增强默认机制.DefaultComponentSafeNamingStrategy是对默认EJB3NamingStrategy的一个小改进,即使在同一实体中使用两次,也允许默认嵌入对象.

来自Hibernate Annotations Doc:http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e714



3> ruediste..:

使用Eclipse Link时,使用AttributeOverrides的替代方法是使用SessionCustomizer.这一次解决了所有实体的问题:

public class EmbeddedFieldNamesSessionCustomizer implements SessionCustomizer {

@SuppressWarnings("rawtypes")
@Override
public void customize(Session session) throws Exception {
    Map descriptors = session.getDescriptors();
    for (ClassDescriptor classDescriptor : descriptors.values()) {
        for (DatabaseMapping databaseMapping : classDescriptor.getMappings()) {
            if (databaseMapping.isAggregateObjectMapping()) {
                AggregateObjectMapping m = (AggregateObjectMapping) databaseMapping;
                Map mapping = m.getAggregateToSourceFields();

                ClassDescriptor refDesc = descriptors.get(m.getReferenceClass());
                for (DatabaseMapping refMapping : refDesc.getMappings()) {
                    if (refMapping.isDirectToFieldMapping()) {
                        DirectToFieldMapping refDirectMapping = (DirectToFieldMapping) refMapping;
                        String refFieldName = refDirectMapping.getField().getName();
                        if (!mapping.containsKey(refFieldName)) {
                            DatabaseField mappedField = refDirectMapping.getField().clone();
                            mappedField.setName(m.getAttributeName() + "_" + mappedField.getName());
                            mapping.put(refFieldName, mappedField);
                        }
                    }

                }
            }

        }
    }
}

}

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有