JPA Multiple Built-In Fields

Is it possible for a JPA entity class to contain two built-in fields ( @Embedded )? An example is:

 @Entity public class Person { @Embedded public Address home; @Embedded public Address work; } public class Address { public String street; ... } 

In this case, a Person can contain two instances of Address - home and work. I am using JPA with the implementation of Hibernate. When I generate a circuit using Hibernate Tools, it includes only one Address . I would like for two built-in instances of Address , each with column names that have been marked or pre-entered in the prefix (for example, home and work). I know @AttributeOverrides , but it requires each attribute to be individually overridden. This can become cumbersome if the built-in object ( Address ) becomes large, since each column must be individually redefined.

+66
java java-ee hibernate jpa
Dec 01 '08 at 18:31
source share
4 answers

If you want to have the same type of inline object twice in the same object, the default value for the column will not work: at least one of the columns must be explicit. Hibernate goes beyond the EJB3 specification and allows you to leverage the default mechanism through NamingStrategy. DefaultComponentSafeNamingStrategy is a small improvement over the default EJB3NamingStrategy, which allows you to use the built-in objects by default, even if they are used twice in the same object.

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

+24
Dec 01 '08 at 19:09
source share

A common JPA way to do this is with @AttributeOverride. This should work in both EclipseLink and 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; ... } } 
+72
Feb 12 '12 at 5:18
source share

When using Eclipse Link, an alternative to using AttributeOverrides is to use the SessionCustomizer. This solves the problem for all objects at a time:

 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); } } } } } } } } 
+3
Mar 16 '16 at 18:14
source share

If you use hibernation, you can also use a different naming scheme that adds unique column prefixes for the same built-in fields. See Automatically Adding a Prefix to Column Names for @Embeddable Classes

+1
Mar 25 '17 at 15:38
source share



All Articles