2011-08-10 19 views
13

Estoy migrando algunas clases en un archivo Hibernate hbm.xml a las anotaciones JPA.Excluir campos de las propiedades @Embedded caso por caso con Hibernate/JPA

Tenemos una clase incrustable Address que se utiliza en varios lugares. Cada lugar usa un subconjunto diferente de las propiedades en Dirección.

(getters/setters omitidos por razones de brevedad)

@Embeddable 
public class Address { 
    String email; 
    String address; 
    String city; 
    String state; 
    String zip; 
    String country; 
} 

@Entity 
@Table(name="customer") 
public class Customer { 
    @Embedded 
    @AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="ship_addr"), 
    @AttributeOverride(name="city", [email protected](name="ship_city"), 
    @AttributeOverride(name="state", [email protected](name="ship_state"), 
    @AttributeOverride(name="zip", [email protected](name="ship_zip"), 
    @AttributeOverride(name="country", [email protected](name="ship_country") 
    }) 
    Address shippingAddress; 

    @Embedded 
    @AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="bill_addr"), 
    @AttributeOverride(name="city", [email protected](name="bill_city"), 
    @AttributeOverride(name="state", [email protected](name="bill_state"), 
    @AttributeOverride(name="zip", [email protected](name="bill_zip") 
    }) 
    Address billingAddress; 
} 

Tenga en cuenta que en este ejemplo artificial, shippingAddress utiliza Address.country, pero billingAddress no lo hace; y ninguno de ellos usa Address.email.

El problema es que Hibernate está infiriendo @Column etiquetas para cualquier columna en la que no haya proporcionado explícitamente una.

He intentado añadir @Transient a todos los campos Address, pero parece que no lo hace de triunfo @AttributeOverride@Transient.

¿Hay alguna solución para esto?

Respuesta

6

No creo que sea posible con las anotaciones "ignorar" un campo de la dirección en sus objetos incrustados.

Una solución alternativa es crear un tipo de base Dirección sin correo electrónico y una Dirección Extendida (subclase de Dirección) con el campo de correo electrónico.

+0

El problema es que esta es una clase de modelo común utilizada en toda nuestra organización. Estoy buscando una forma de migrar esta clase a JPA sin cambiar el comportamiento, o forzar a 30 equipos diferentes a ajustar su código. – qualidafial

+0

Tenga en cuenta también que este es un problema con el cambio de la opción de exclusión voluntaria de JPA utilizando &at; Transitorio, en lugar de optar por la columna &at;. La idea era hacer que la adopción de JPA fuera menos invasiva al no requerir &at; Anotaciones de columna en todas partes; esto es solo un efecto secundario que nos ha picado y ha hecho imposible migrar esta clase desde la configuración XML heredada a las anotaciones JPA. – qualidafial

+0

Si no puede cambiar su modelo, entonces no veo una solución. Simplemente tendrá que ignorar las propiedades de la dirección que no se utilizan, y así dejarlas en blanco en la base de datos. Solución sucia, pero la menos invasiva. –

6

Mi consejo sería crear una nueva entidad llamada ParcialAddress/NationalAddress/BillingAddress. Esto se usaría sólo para el mapeo de la APP, y no se expone en la interfaz del cliente:

private PartialAddress billingAddress; 

public Address getBillingAddress() { 
    return billingAddress.toAddress(); 
} 

De lo contrario, me han llegado con una solución un tanto desagradable para este problema, tal vez va a trabajar para usted también. En lugar de mapear el campo a una columna de bienes, vuelvo una constante nula SQL:

@Embedded 
@AttributeOverrides({ 
    @AttributeOverride(name="address", [email protected](name="bill_addr"), 
    @AttributeOverride(name="city", [email protected](name="bill_city"), 
    @AttributeOverride(name="state", [email protected](name="bill_state"), 
    @AttributeOverride(name="zip", [email protected](name="bill_zip"), 
    @AttributeOverride(name="country", [email protected](name="bill_id + null"), 
}) 
Address billingAddress; 

Estoy usando Oracle y EclipseLink, trabaja en Hibernate 3.6 también. Y solo lo he probado en objetos de solo lectura. Aunque, teóricamente, configurar los atributos insertable y updatable en falso debería ser suficiente.

+2

Esta es una solución muy buena e innovadora. Yo directamente mapeo la propiedad ignorada a nulo (es decir 'column = @ Column (name =" null ")' –

+0

La solución de @KenChan es aceptable para los datos persistentes, pero hay un problema al leer de la base de datos. "javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: no se pudo extraer ResultSet" y el mensaje dice: "ohejsSqlExceptionHelper - ERROR: column not found tabl0_.null" –