JPAエンティティクラスに2つの埋め込み(@Embedded
) 田畑?例は次のとおりです。
@Entity
public class Person {
@Embedded
public Address home;
@Embedded
public Address work;
}
public class Address {
public String street;
...
}
この場合、Person
には2つのAddress
インスタンス(自宅と職場)を含めることができます。 Hibernateの実装でJPAを使用しています。 Hibernate Toolsを使用してスキーマを生成すると、1つのAddress
のみが埋め込まれます。私が望んでいるのは、2つの埋め込みAddress
インスタンスで、それぞれの列名が区別されているか、いくつかのプレフィックス(homeやworkなど)が前に付いています。 @AttributeOverrides
、ただしこれには各属性を個別にオーバーライドする必要があります。各列を個別にオーバーライドする必要があるため、埋め込みオブジェクト(Address
)が大きくなると、これは面倒になります。
同じエンティティに同じ埋め込みオブジェクトタイプを2回使用する場合、列名のデフォルト設定は機能しません。少なくとも1つの列を明示的に指定する必要があります。 HibernateはEJB3仕様を超えており、NamingStrategyを介してデフォルトのメカニズムを強化できます。 DefaultComponentSafeNamingStrategyは、デフォルトのEJB3NamingStrategyをわずかに改善したもので、同じエンティティで2回使用した場合でも埋め込みオブジェクトをデフォルトに設定できます。
Hibernate Annotations Docから: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e714
一般的な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;
...
}
}
Eclipse Linkを使用する場合、AttributeOverrideを使用する代わりに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);
}
}
}
}
}
}
}
}
Hibernateを使用している場合は、同じ埋め込みフィールドの列に一意のプレフィックスを追加する別の命名スキームを使用することもできます。 @ Embeddableクラスの列名に自動的にプレフィックスを追加する を参照してください