2009-07-09 31 views
5

Ho un oggetto utente che ha una relazione uno-a-molti con i tipi di stringa. Credo che siano semplici mappature. La tabella dei tipi contiene i nomi user_id e di tipo variabile associati, con una chiave primaria 'id' che è fondamentalmente un contatore.Sospensione Salva comportamento strano

<class name="Users" table="users"> 
    <id column="id" name="id" /> 
    ... 
    <set name="types" table="types" cascade="save-update"> 
     <key column="id" /> 
     <one-to-many class="Types" /> 
    </set> 
</class> 

<class name="Types" table="types"> 
    <id column="id" name="id" /> 
    <property column="user_id" name="user_id" type="integer" /> 
    <property column="type" name="type" type="string" /> 
</class> 

Questa è la java che ho usato per l'aggiunta al database:

User u = new User(); 
u.setId(user_id); 
... 
Collection<Types> t = new HashSet<Types>(); 
t.add(new Type(auto_incremented_id, user_id, type_name)); 
u.setTypes(t); 

getHibernateTemplate().saveOrUpdate(u); 

quando l'eseguo, dà questo errore:

61468 [http-8080-3] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000 
61468 [http-8080-3] ERROR org.hibernate.util.JDBCExceptionReporter - Duplicate entry '6' for key 'PRIMARY' 
61468 [http-8080-3] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session 
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 

Quando controllo l'SQL, mostra:

Hibernate: insert into users (name, id) values (?, ?) 
Hibernate: insert into types (user_id, type, id) values (?, ?, ?) 
Hibernate: update types set id=? where id=? 
  • Perché Hibernate tenta di aggiornare l'id dei tipi?

L'errore dice: Duplica la voce '6' per la chiave 'PRIMARY', ma in realtà non lo è? Mi sono assicurato che gli ID vengano incrementati ogni volta. E gli utenti e i tipi vengono aggiunti correttamente nel database.

Ho registrato le informazioni in entrata, e i tipi aggiunti hanno un id di 7 e un id utente di 6. Potrebbe essere che Hibernate prende l'id utente di 6 e ha provato ad aggiornare i tipi e impostare id = 6 dove id = 7? Quindi l'errore della chiave primaria duplicata?

Ma perché dovrebbe fare qualcosa di così strano? C'è un modo per impedirne l'aggiornamento?

  • Devo impostare l'ID manualmente? Se no, allora come dovrei aggiungere i tipi? Fornisce altri errori quando aggiungo un oggetto tipo che contiene solo una stringa di testo e nessun ID.

Grazie ragazzi. Stai rimuginando per giorni ...

risposta

2

Il tuo problema più grande è colonna errata nel mapping <key> - dovrebbe essere "user_id", non "id". Detto questo, l'intera mappatura mi sembra un po 'strana.

Prima di tutto, se si desidera che gli ID generato automaticamente si dovrebbe davvero lasciare che Hibernate prendersi cura di ciò specificando generatore appropriata:

 
<id column="id" name="id"> 
    <generator class="native"/> 
</id> 

Hibernate Documentation Leggi su generatori per le varie opzioni disponibili. li

In secondo luogo, se tutto ciò che serve è un insieme di tipi di stringhe, in considerazione ri-mappare in un insieme di elementi, piuttosto che uno-a-molti:

 
<set name="types" table="types"> 
    <key column="user_id"/> 
    <element column="type" type="string"/> 
</set> 

In questo modo non sarà necessario classe "Tipi" esplicita o mappatura per esso. Anche se si desidera avere attributi aggiuntivi su "Tipi", è comunque possibile mapparlo come componente anziché come entità.

Infine, se "Tipi" deve essere un'entità a causa di qualche requisito non è stato descritto, il rapporto tra "Utenti" e "Tipi" è bidirezionale e deve essere mappato come tale:

 
<set name="types" table="types" inverse="true"> 
    <key column="user_id"/> 
    <one-to-many class="Types"/> 
</set> 

... 
in Types mapping: 
<many-to-one name="user" column="user_id" not-null="true"/> 

In quest'ultimo caso "Tipi" dovrebbe avere una proprietà "utente" di tipo "Utenti". Here è un esempio dettagliato.

+0

bloccato con raccolta di elementi! Grazie! – April

0

La soluzione che ha funzionato per me era quello di salvare separatamente le due parti (senza aggiungere tipo di utente):

getHibernateTemplate().save(user); 
getHibernateTemplate().save(new Type(user.id, type_name)); 

E con la < class generatore = "nativo" /> sul solo i tipi di id.

Cattiva pratica?

L'aveva mappato come una raccolta di elementi, ma aggiungeva in qualche modo erroneamente user_id alla colonna id di tipi che a volte causa un errore duplicato; poiché id di tipi è l'unica colonna di chiave primaria. Strano! Ricordo che c'era un altro errore nella colonna, ma me ne sono dimenticato, perché sono tornato immediatamente a uno-a-molti. Impossibile cogliere le strane funzionamento di Hibernate ...

cercherò la soluzione bi-direzionale a volte ... Grazie mille per tutto l'aiuto :)

+1

Ho paura che manchi completamente il punto. Dovresti lasciare che Hibernate ti semplifichi la vita, non combatterlo in ogni fase del percorso, e avere mappature corrette farebbe molto per raggiungerlo. Lo scenario che hai descritto sopra è molto semplice; ci sono molti esempi disponibili (ho postato dei link nella mia risposta). Hai davvero bisogno di leggere la documentazione, farlo funzionare e capire _come_ funziona; altrimenti diventerà molto più difficile lungo la strada. – ChssPly76

+0

Sì, lo so che è molto semplice, quindi sono confuso perché si rompe ancora. Usando questa soluzione, la modalità hibernate prova a cercare i tipi, facendo corrispondere l'id del tipo a user_id che è completamente strano. Così ho fatto la raccolta di elementi di cui sopra, e sto avendo errore di cast di classe ora. Fare i mapping per Hibernate rende la vita così difficile! Ogni volta che c'è una mappatura, non seguono un modo in cui gli oggetti possono essere consultati o recuperati. Devi cercare e scavare in qualche altro posto. – April