struttura del database Legacy problema mapping Hibernate
-
30-09-2019 - |
Domanda
Ho problemi mappare la seguente struttura del database (abbreviata per brevità con PKS solo / FKS e alcune colonne in più:
Politica
Policy_Id (PK) ...
rischio
Risk_Id (PK) ...
Partito
Party_Id (PK) ...
PartyRole
- PartyRole_Id (PK)
- Party_Id (FK non-null)
- Policy_Id (FK)
- Risk_Id (FK)
- Party_Role_Type
Quindi la tabella PartyRole può contenere una riga che i collegamenti di un partito ad una politica e / o di una riga che collega la stessa parte di un rischio. Fondamentalmente si tratta di una relazione molti a molti join tavolo, ma combina molti a molti rapporti: Partito <-> politica e uno per partito <-> Rischio. Party_Role_Type può essere criterio o PARTI ed agisce efficacemente come un discriminatore per identificare quale relazione la riga a cui appartiene.
ho cercato di modellare questa struttura con un 4 entità: la politica, parte, dei rischi, PartyRole. Qui ci sono le mappature: Codice:
<class name="com.blah.Party" table="Party">
<id column="Party_Id" name="_id" type="int" unsaved-value="-1" access="field">
<generator class="sequence">
<param name="sequence">SQ_Party</param>
</generator>
</id>
<bag name="_policyRoles" access="field" table="Party_Role">
<key column="Policy_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
<bag name="_riskRoles" access="field" table="Party_Role">
<key column="Risk_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
</class>
<class name="com.blah.Risk" table="Risk">
<id column="Risk_Id" name="_id" type="int" unsaved-value="-1" access="field">
<generator class="sequence">
<param name="sequence">SQ_Risk</param>
</generator>
</id>
<bag name="_partyRoles" access="field">
<key column="Risk_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
</class>
<class name="com.blah.Policy" table="Policy">
<id column="Policy_Id" name="_id" type="int" unsaved-value="-1" access="field">
<generator class="sequence">
<param name="sequence">SQ_Policy</param>
</generator>
</id>
<bag name="_partyRoles" inverse="true" cascade="save-update" access="field" table="Party_Role" >
<key column="Policy_Id" />
<one-to-many class="au.com.cgu.harvest.domain.party.PartyRole" />
</bag>
</class>
<class name="au.com.cgu.harvest.domain.party.PartyRole" table="Party_Role" schema="Harvest">
<id column="Party_Role_Id" name="_id" type="int" unsaved-value="-1" access="field">
<generator class="sequence">
<param name="sequence">Harvest.SQ_Party_Role</param>
</generator>
</id>
<property name="partyRoleType" column="PARTY_ROLE_TYPE"
type="java.lang.String" />
<many-to-one name="_party" column="Party_Id" class="com.blah.Party" access="field" cascade="save-update" fetch="join" />
<many-to-one name="_risk" column="Risk_Id" class="com.blah.Risk" access="field" />
<many-to-one name="_policy" column="Policy_Id" class="com.blah.Policy" access="field" />
</class>
Tutti i POJO java sono stati impostati per corrispondere a questo mappatura e tutte le associazioni sono configurato correttamente quando gli oggetti aggiunti o eliminati in collezioni. Politica è considerato una radice di aggregazione, in modo che quando viene salvato da Hibernate voglio salvare le Parti associate con la politica. Quando aggiungo una parte della politica e del rischio (e tutti i ruoli associati) ottengo la seguente eccezione:
Causato da: java.sql.BatchUpdateException: l'integrità violazione del vincolo: chiave esterna nessun genitore; tavolo FK_PARTY_ROLE_POLICY: PARTY_ROLE
Cosa c'è di sbagliato? Anche è questo il modo migliore per mappare questa relazione? C'è la possibilità di mappare in qualche modo questo rapporto senza l'uso del soggetto intermedio? Grazie per tutto quello che di aiuto.
Soluzione
non ho davvero avuto la possibilità di tornare a scrivere una risposta a questo, ma ho trovato quale fosse il problema. Il problema è stato in queste righe qui:
<bag name="_policyRoles" access="field" table="Party_Role">
<key column="Policy_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
<bag name="_riskRoles" access="field" table="Party_Role">
<key column="Risk_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
I stupidamente perso che la "colonna" specificato negli elementi delle borse punta ad Policy_Id e Risk_Id, che non è corretto. Dovrebbe essere il nome del chiave esterna colonna che fa riferimento al chiave primaria del soggetto in cui sono definite le borse uno-a-molti. Quindi, nel mio caso avrebbe dovuto essere Party_Id e di distinguere tra ruoli politici e ruoli di partito, ho dovuto usare un "dove" constrant sulla borsa. Così le definizioni finito per assomigliare a questo:
<bag name="_policyRoles" access="field" table="Party_Role" where="Party_Role_Type = 'POLICY'">
<key column="Party_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
<bag name="_riskRoles" access="field" table="Party_Role" where="Party_Role_Type = 'RISK'">
<key column="Party_Id" />
<one-to-many class="com.blah.PartyRole" />
</bag>
Altri suggerimenti
Sembra a me che questo è un errore generato dai vostri RDBMS. Quindi, cercare di abilitare la registrazione SQL (hibernate.show_sql = true) e vedere cosa Hibernate sta cercando di fare. Ma vorrei controllare due volte la struttura della tabella per PARTY_ROLE, come sembra che i FKS sono stati creati con vincoli non-nulli. Ci sono alcuni database (Sybase, IIRC) che crea le FKS con non-null per impostazione predefinita. E, se si specifica la relazione come NULL, si può tentare di trovare una politica con il NULL ID, che certamente non esisterà :-)