84

JPAエンティティクラスに2つの埋め込み(@Embedded)フィールドを含めることは可能ですか?例は次のとおりです。

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

    @Embedded
    public Address work;
}

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

この場合、aには自宅と職場Personの2つのインスタンスを含めることができます。AddressHibernateの実装でJPAを使用しています。Hibernate Toolsを使用してスキーマを生成すると、埋め込まれるのは1つだけAddressです。私が欲しいのは、2つの埋め込みAddressインスタンスで、それぞれの列名が区別されるか、接頭辞(自宅や職場など)が前に付けられます。私は知って@AttributeOverridesいますが、これには各属性を個別にオーバーライドする必要があります。Address各列を個別にオーバーライドする必要があるため、埋め込みオブジェクト()が大きくなると、これは面倒になる可能性があります。

4

4 に答える 4

89

これを行う一般的な 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;
    ...
  }
}
于 2012-02-12T05:18:25.463 に答える
29

同じエンティティに同じ埋め込み可能オブジェクトタイプを2回持つ場合、列名のデフォルトは機能しません。少なくとも1つの列が明示的である必要があります。HibernateはEJB3仕様を超えており、NamingStrategyを介してデフォルトメカニズムを拡張できます。DefaultComponentSafeNamingStrategyは、デフォルトのEJB3NamingStrategyを少し改善したもので、同じエンティティで2回使用された場合でも、埋め込みオブジェクトをデフォルトにすることができます。

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

于 2008-12-01T19:09:07.520 に答える
6

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

                }
            }

        }
    }
}

}
于 2016-03-16T18:14:39.630 に答える
1

休止状態を使用している場合は、同じ埋め込みフィールドの列に一意のプレフィックスを追加する別の命名スキームを使用することもできます。@Embeddable クラスの列名にプレフィックスを自動的に追加するを参照してください。

于 2017-03-25T15:38:09.073 に答える