2008-12-01 31 views
68

Có thể cho lớp thực thể JPA chứa hai trường được nhúng (@Embedded) không? Một ví dụ sẽ là:JPA Nhiều trường được nhúng

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

    @Embedded 
    public Address work; 
} 

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

Trong trường hợp này một Person có thể chứa hai Address trường - gia đình và công việc. Tôi đang sử dụng JPA với việc thực hiện Hibernate. Khi tôi tạo lược đồ bằng cách sử dụng Công cụ Hibernate, nó chỉ nhúng một Address. Những gì tôi muốn là hai trường hợp Address được nhúng, mỗi trường hợp có tên cột được phân biệt hoặc được mở trước bằng một số tiền tố (chẳng hạn như nhà riêng và cơ quan). Tôi biết về @AttributeOverrides, nhưng điều này yêu cầu mỗi thuộc tính phải được ghi đè riêng. Điều này có thể trở nên rườm rà nếu đối tượng được nhúng (Address) trở nên lớn vì mỗi cột cần phải được ghi đè riêng.

Trả lời

25

Nếu bạn muốn có cùng một loại đối tượng có thể nhúng hai lần trong cùng một thực thể, việc đặt tên cột sẽ không hoạt động: ít nhất một trong các cột sẽ phải rõ ràng. Hibernate vượt ra ngoài thông số kỹ thuật EJB3 và cho phép bạn tăng cường cơ chế mặc định thông qua NamingStrategy. DefaultComponentSafeNamingStrategy là một cải tiến nhỏ so với EJB3NamingStrategy mặc định cho phép các đối tượng nhúng được mặc định ngay cả khi được sử dụng hai lần trong cùng một thực thể.

Từ Hibernate Annotations Đốc: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#d0e714

74

Các generic JPA cách để làm điều đó là với @AttributeOverride. Điều này sẽ làm việc trong cả EclipseLink và 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

Lưu ý rằng 'name =" street "' là tên của thuộc tính chứ không phải tên cột. –

3

Khi sử dụng Eclipse Link, một thay thế cho việc sử dụng Thuộc tínhOverrides nó để sử dụng SessionCustomizer. Điều này giải quyết vấn đề này cho tất cả các đối tượng trong một đi:

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 Sẽ tốt hơn nếu có điều này như là một DescriptorCustomizer, để có thể kiểm soát điều này cho mỗi lớp, nhưng tôi đã không tìm thấy một cách để truy cập ClassDescriptor của lớp được nhúng từ bên trong DescriptorCustomizer của lớp máy chủ. – oulenz

+0

Cách thay thế mà tôi đang sử dụng bây giờ là kiểm tra 'classDescriptor.getJavaClass()' trong SessionCustomizer với một danh sách các lớp mà tôi muốn nó ảnh hưởng. – oulenz

Các vấn đề liên quan