簡體   English   中英

JPA Multiple Embedded字段

[英]JPA Multiple Embedded fields

JPA實體類是否可以包含兩個嵌入( @Embedded )字段? 一個例子是:

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

    @Embedded
    public Address work;
}

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

在這種情況下, Person可以包含兩個Address實例 - home和work。 我正在使用JPA和Hibernate的實現。 當我使用Hibernate Tools生成模式時,它只嵌入一個Address 我想要的是兩個嵌入的Address實例,每個實例的列名都有區別或預先設置了一些前綴(例如家庭和工作)。 我知道@AttributeOverrides ,但這需要單獨覆蓋每個屬性。 如果嵌入對象( Address )變大,因為每個列都需要單獨覆蓋,這會很麻煩。

通用的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;
    ...
  }
}

如果要在同一實體中兩次使用相同的可嵌入對象類型,則列名默認將不起作用:至少有一列必須是顯式的。 Hibernate超越了EJB3規范,允許您通過NamingStrategy增強默認機制。 DefaultComponentSafeNamingStrategy是對默認EJB3NamingStrategy的一個小改進,即使在同一實體中使用兩次,也允許默認嵌入對象。

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

使用Eclipse Link時,使用AttributeOverrides的替代方法是使用SessionCustomizer。 這一次解決了所有實體的問題:

public class EmbeddedFieldNamesSessionCustomizer implements SessionCustomizer {

@SuppressWarnings("rawtypes")
@Override
public void customize(Session session) throws Exception {
    Map<Class, ClassDescriptor> descriptors = session.getDescriptors();
    for (ClassDescriptor classDescriptor : descriptors.values()) {
        for (DatabaseMapping databaseMapping : classDescriptor.getMappings()) {
            if (databaseMapping.isAggregateObjectMapping()) {
                AggregateObjectMapping m = (AggregateObjectMapping) databaseMapping;
                Map<String, DatabaseField> 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);
                        }
                    }

                }
            }

        }
    }
}

}

如果您正在使用休眠,您還可以使用不同的命名方案,為相同的嵌入字段的列添加唯一的前綴。 請參閱自動為@Embeddable類的列名添加前綴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM