2009-11-30 19 views
10

Possiedo un oggetto prodotti appartenente a determinate categorie, vale a dire una relazione classica da molti a uno.Sospensione, inserimento o aggiornamento senza selezionare

@Entity 
public class Product{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    Long id; 

    String name; 
    Double price; 
    @ManyToOne(fetch = FetchType.LAZY) 
    Category category; 
... 
} 

@Entity 
public class Category implements Identifiable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String name; 
... 
} 

Voglio inserire e aggiornare prodotti senza preselezionare le categorie. Come questo:

Product product = dao.get(productId); 
Category category = dao.get(categoryId); 
product.setCategory(category); 
dao.update(product); 

o

Product product = new Product(somename); 
Category category = dao.get(categoryId); 
product.setCategory(category); 
dao.insert(product); 

E 'possibile aggiornare e inserire senza categoria selezionare? Non voglio usare HQL o query dirette per questo.

risposta

10

session.load() esiste specificamente per casi come questo. Il seguente:

Category category = session.load(categoryId); 
product.setCategory(category); 

non colpirà il database. Tuttavia, genererà un'eccezione in una fase successiva (durante il flush, più o meno) se non ci sono categorie disponibili con un determinato ID.

Utilizzando load() è più veloce di merge() e non ha effetti collaterali (a cascata, ecc ...)

2

Hibernate richiede un modo sicuro per determinare lo stato dell'oggetto. Ecco perché sta facendo molto per assicurarsi di non poter mescolare oggetti da sessioni diverse (quindi non è possibile caricare le categorie all'avvio e poi usarle in seguito).

La soluzione è quella di caricare le categorie in fase di avvio, impostare un provider di caching come ehcache per questa classe e quindi utilizzare questo codice:

Product product = new Product(somename); 
product.setCategory(session.merge(category)); 

tale da non causare alcun round trip DB se si configura il cache che le istanze di categoria non possono cambiare.

0

Ho appena provato seguente:

Category category = new Category(categoryId); 
product.setCategory(category); 

e ha funzionato, voglio dire record del prodotto in db ha ottenuto il collegamento corretto alla categoria e alla categoria con ID

categoryId 

non sono stati modificati.

+1

Il problema con questo approccio è che stai creando una nuova istanza di entità persistente con lo stesso identificatore. Potrebbe aver funzionato per te questa volta perché la categoria "in questione" non era associata alla ** sessione ** corrente; se lo fosse, Hibernate avrebbe lanciato un'eccezione. È anche pericoloso in termini di integrità dei dati; se dovessi specificare la cascata per il tuo molti-su-su 'category', il codice sopra sovrascriverebbe la tua categoria originale con tutti i valori vuoti (o fallirebbe con l'errore di violazione dei vincoli) – ChssPly76

+0

Hm, avevo la sensazione che io stia facendo qualcosa di brutto qui. Grazie per il chiarimento. – Vladimir

Problemi correlati