JPA несколько встроенных полей
возможно ли, чтобы класс сущности JPA содержал два встроенных (@Embedded) поля? Примером может быть:
@Entity
public class Person {
@Embedded
public Address home;
@Embedded
public Address work;
}
public class Address {
public String street;
...
}
в этом случае a Person может содержать два Address экземпляры-дом и работа. Я использую JPA с реализацией Hibernate. Когда я создаю схему с помощью инструментов Hibernate, она встраивает только один Address. То, что я хотел бы два встроенных Address экземпляры, каждый из которых имеет свои имена столбцов, отличающиеся или предварительно добавленные с некоторым префиксом (например, home и work). Я знаю из @AttributeOverrides, но это требует, чтобы каждый атрибут быть индивидуально изменено. Это может стать громоздким, если встроенный объект (Address) имел большой, как каждый столбец должен быть индивидуально изменено.
4 ответов:
Если вы хотите иметь один и тот же тип встраиваемого объекта дважды в одной и той же сущности, имя столбца по умолчанию не будет работать: по крайней мере один из столбцов должен быть явным. Hibernate выходит за рамки спецификации EJB3 и позволяет улучшить механизм дефолта через NamingStrategy. DefaultComponentSafeNamingStrategy-это небольшое улучшение по сравнению с ejb3namingstrategy по умолчанию, которое позволяет использовать встроенные объекты по умолчанию, даже если они используются дважды в одном и том же объекте.
от Hibernate аннотации 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 альтернативой использованию 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); } } } } } } } }
Если вы используете hibernate, вы также можете использовать другую схему именования, которая добавляет уникальные префиксы к столбцам для идентичных встроенных полей. Смотрите автоматическое добавление префикса к именам столбцов для @ Embeddable Classes
Comments