2008-12-01 2 views
68

Возможно ли, чтобы класс сущности JPA содержал два встроенных поля (@Embedded)? Примером может быть:JPA Несколько встроенных полей

@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, но это требует, чтобы каждый атрибут был индивидуально переопределен. Это может стать громоздким, если встроенный объект (Address) становится большим, поскольку каждый столбец должен быть индивидуально переопределен.

ответ

25

Если вы хотите иметь один и тот же тип встраиваемого объекта дважды в одном и том же объекте, то по умолчанию значение имени столбца не будет работать: по крайней мере один из столбцов должен быть явным. Hibernate выходит за рамки спецификации EJB3 и позволяет вам усилить механизм дефолта через NamingStrategy. DefaultComponentSafeNamingStrategy - небольшое улучшение по сравнению с EJB3NamingStrategy по умолчанию, которое позволяет использовать встроенные объекты по умолчанию, даже если они используются дважды в одном и том же объекте.

С Hibernate Аннотации Doc: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e714

74

Общий способ JPA сделать это с @AttributeOverride. Это должно работать как в EclipseLink, так и в Hibernate.

@Entity 
public class Person { 
    @AttributeOverrides({ 
    @AttributeOverride(name="street",[email protected](name="homeStreet")), 
    ... 
    }) 
    @Embedded public Address home; 

    @AttributeOverrides({ 
    @AttributeOverride(name="street",[email protected](name="workStreet")), 
    ... 
    }) 
    @Embedded public Address work; 
    } 

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

Обратите внимание, что `name =" street "означает имя свойства, а не имя столбца. – 2015-08-17 14:41:44

3

При использовании 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); 
         } 
        } 

       } 
      } 

     } 
    } 
} 

} 
+0

+1 Было бы неплохо иметь это как DescriptorCustomizer, чтобы иметь возможность контролировать это для каждого класса, но я не нашел способ получить доступ к ClassDescriptor встроенного класса из DescriptorCustomizer класса хоста. – oulenz 2016-09-19 13:47:00

1

В случае, если вы используете спящий режим можно также использовать другую схему именования, которая добавляет уникальные префиксы столбцов для идентичных встроенных полей. См. Automatically Add a Prefix to Column Names for @Embeddable Classes

Смежные вопросы