2010-05-15 26 views
9

Hibernate no me permite persistir un objeto que contiene un objeto incrustado nulo con un campo entero. Por ejemplo, si tengo una clase llamada cosa que tiene este aspectoHibernate no permite que un objeto incrustado con un campo int sea nulo?

@Entity 
public class Thing { 

    @Id 
    public String id; 

    public Part part; 

} 

donde la Parte es una clase incrustada que tiene este aspecto

@Embeddable 
public class Part { 

    public String a;  

    public int b; 

} 

continuación, tratando de conservar un objeto de Cosa con un nulo causas Parte Hibernate para lanzar una excepción. En particular, este código

Thing th = new Thing(); 
th.id = "thing.1"; 
th.part = null; 
session.saveOrUpdate(th); 

causas Hibernate para lanzar esta excepción

org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ace.moab.api.jobs.Thing.part 

Mi conjetura es que esto está sucediendo porque la Parte es una clase incrustada y así Part.a y Part.b son simplemente columnas en la tabla de la base de datos de Thing. Como The Thing.part es nulo, Hibernate quiere establecer los valores de la columna Part.a y Part.b en null para la fila para thing.1. Sin embargo, Part.b es un número entero e Hibernate no permitirá que las columnas enteras en la base de datos sean nulas. Esto es lo que causa la Excepción, ¿verdad?

Así que estoy buscando soluciones para este problema. Noté que hacer Part.b un entero en vez de un int parece funcionar, pero por razones que no te aburriré con esto no es una buena opción para nosotros. ¡Gracias!

Respuesta

7

Encontré otra solución y pensé en compartirla. Resulta que si hace que la columna int sea nulable, Hibernate no lanzará la PropertyValueException.

@Column(nullable = true) 
public Integer b; 

Esto funciona para nosotros porque nuestra aplicación habilitada hibernación es el único que tocó la base de datos y por lo que podemos garantizar que b es nulo sólo cuando la pieza es nula. Aunque la sugerencia de la parte nula y el uso del tipo de envoltura Integer son excelentes sugerencias, debido a muchas razones por las que realmente no tengo control, configurar la columna para el valor nulo es mejor para nosotros. Sin embargo, gracias y espero que esto ayude a alguien más.

+0

¿Cómo será su int nulo cuando 'b' es una primitiva? –

+0

Deberías estar usando una clase contenedora (Integer) para cualquier cosa que sea anulable ... – Amalgovinus

1

Tiene toda la razón sobre lo que está sucediendo. Cuando un objeto de una clase incrustada es nulo, Hibernate lo representa haciendo que todas sus columnas sean nulas en la base de datos; desafortunadamente, esto significa que Hibernate no puede distinguir entre un objeto embebible nulo y un objeto incrustable con todos los valores nulos.

Por lo que sé, si no puede hacer que el campo sea nulo (por lo que es Integer, como ya adivinó), la única forma de evitar esto es crear un tipo Hibernate personalizado. Debería ser factible, pero será un dolor hacerlo de esa manera. De hecho, probablemente sea peor que cualquiera que sea la razón por la que no puedes usar un Entero, entonces, ¿cuál es esa razón?

3

Bastante incómodo, sí. Se puede establecer un valor predeterminado para el campo part:

private Part part = new Part(); 

o incluso

private Part part = Part.NULL_PART; 

(ver Null object patern)

Tenga en cuenta, que si la clase @Embeddable no contiene una primitiva (que tiene un valor predeterminado), y guarda un objeto con todos los null s, toda la estructura se mantendrá en la base de datos como null, porque no hay forma de que hibernate haga th La diferencia en el DB ya sea que no tenga un objeto o que tenga uno vacío. Para solucionar este problema, si surge, debe crear un campo ficticio (es mejor boolean).

Cuestiones relacionadas