2010-05-15 7 views
9

Hibernate non mi consente di mantenere un oggetto che contiene un oggetto incorporato null con un campo intero. Per esempio, se ho una classe denominata Cosa che assomiglia a questoHibernate non consente ad un oggetto incorporato con un campo int di essere nullo?

@Entity 
public class Thing { 

    @Id 
    public String id; 

    public Part part; 

} 

cui parte è una classe integrabile che assomiglia a questo

@Embeddable 
public class Part { 

    public String a;  

    public int b; 

} 

poi cercando di persistere un oggetto cosa con un nulli cause Parte Iberna per lanciare un'eccezione. In particolare, questo codice

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

cause Hibernate per lanciare questa eccezione

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

La mia ipotesi è che questo sta accadendo perché una parte è una classe embedded e così Part.a e Part.b sono semplicemente le colonne nella tabella del database Thing. Poiché Thing.part è null, Hibernate desidera impostare i valori della colonna Part.a e Part.b su null per la riga per thing.1. Tuttavia, Part.b è un numero intero e Hibernate non consente alle colonne integer nel database di essere nulle. Questo è ciò che causa l'eccezione, giusto?

Quindi sto cercando soluzioni alternative per questo problema. Ho notato che rendere Part.b un intero invece di un int sembra funzionare, ma per ragioni che non ti annoierò non è una buona opzione per noi. Grazie!

risposta

7

Ho trovato un'altra soluzione e ho pensato di condividerlo. Si scopre che se si rende nullable la colonna int Hibernate non lancia l'eccezione PropertyValueException.

@Column(nullable = true) 
public Integer b; 

Questo funziona per noi, perché la nostra applicazione di sospensione abilitata è l'unica cosa che ha toccato il database e così possiamo garantire che b è nullo solo quando la parte è nullo. Anche se il suggerimento di parte nullo e l'uso del tipo di wrapper Integer sono ottimi suggerimenti, a causa di molte ragioni per le quali non ho realmente il controllo, impostare la colonna su nullable funziona meglio per noi. Grazie però e spero che questo aiuti qualcun altro.

+0

Come sarà il tuo int nullo quando 'b' è un primitivo? –

+0

Dovresti usare una classe wrapper (Intero) per tutto ciò che è nullable ... – Amalgovinus

1

Hai assolutamente ragione su ciò che sta accadendo. Quando un oggetto di una classe incorporata è nullo, Hibernate lo rappresenta rendendo tutte le sue colonne nulle nel database; sfortunatamente, questo significa che Hibernate non può distinguere tra un oggetto nullo e un oggetto integrabile con tutti i valori nulli.

Per quanto ne so, se non è possibile rendere nulla il campo (rendendolo un Integer, come hai indovinato), l'unico modo per aggirare questo è quello di creare un tipo Hibernate personalizzato. Dovrebbe essere fattibile, ma sarà doloroso farlo in quel modo. In realtà, sarebbe probabilmente peggio di qualunque sia la ragione per cui non è possibile utilizzare un intero - quindi qual è la ragione, comunque?

3

Abbastanza scomodo, sì. È possibile impostare un valore predefinito per la part campo:

private Part part = new Part(); 

o anche

private Part part = Part.NULL_PART; 

(vedi Null object patern)

Tenete a mente, che se la classe @Embeddable non contiene un primitivo (che ha un valore predefinito) e si salva un oggetto con tutti i null s, l'intera struttura verrà mantenuta nel database come null, perché non c'è un modo per ibernare La differenza nel DB se non hai un oggetto o ne hai uno vuoto. Per ovviare al problema, in caso affermativo, è necessario creare un campo fittizio (boolean è il migliore).

Problemi correlati