2017-05-20 3 views
0

J'ai un problème avec les mappages d'hibernation en conjonction avec l'audit. Ma classe java avec la cartographie:Hibernate @ElementCollection Carte avec @Audited créer une violation de clé en double sur la mise à jour

@Entiy 
@Audited 
@Table(name = "farm_detail") 
public class FarmDetail { 
    @Id 
    private Long id; 

    @ElementCollection 
    @MapKeyColumn(name = "field_id") 
    @Column(name = "remark") 
    @CollectionTable(name = "farm_detail_remark", joinColumns = @JoinColumn(name = "farm_detail_id")) 
    private Map<String, String> fieldRemarks = new HashMap<>(); 
    // Getter, Setter, etc 
} 

La définition sql des tables farm_detail_remark et farm_detial_remark_aud:

db=# \d farm_detail_remark 
      Table "public.farm_detail_remark" 
    Column  |   Type   | Modifiers 
----------------+------------------------+----------- 
farm_detail_id | bigint     | not null 
field_id  | character varying(255) | not null 
remark   | character varying  | not null 
Indexes: 
    "farm_detail_remark_pkey" PRIMARY KEY, btree (farm_detail_id, field_id) 
Foreign-key constraints: 
    "farm_detail_remark_farm_detail_id_fkey" FOREIGN KEY (farm_detail_id) REFERENCES farm_detail(id) 

db=# \d farm_detail_remark_aud 
     Table "public.farm_detail_remark_aud" 
    Column  |   Type   | Modifiers 
----------------+------------------------+----------- 
rev   | integer    | not null 
revtype  | smallint    | 
farm_detail_id | bigint     | not null 
field_id  | character varying(255) | not null 
remark   | character varying  | 
Indexes: 
    "farm_detail_remark_aud_pkey" PRIMARY KEY, btree (rev, farm_detail_id, field_id) 
Foreign-key constraints: 
    "farm_detail_remark_aud_rev_fkey" FOREIGN KEY (rev) REFERENCES revinfo(rev) 

Si je veux mettre à jour une entrée du fieldRemarks ensemble je reçois une clé doublon sur la farm_detail_remark_aud tableau. En activant l'enregistrement sql j'ai découvert que veille prolongée tente d'insérer deux entrées dans la table aud:

Hibernate: 
    /* insert farm_detail_remark_AUD 
     */ insert 
     into 
      farm_detail_remark_aud 
      (revtype, rev, farm_detail_id, remark, field_id) 
     values 
      (?, ?, ?, ?, ?) 
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [1] as [INTEGER] - [0] 
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [2] as [INTEGER] - [1057] 
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [3] as [BIGINT] - [110] 
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [4] as [VARCHAR] - [Old remark] 
21:20:58.188 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [5] as [VARCHAR] - [152] 

et (seulement PARAM lier ici):

21:20:58.193 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [1] as [INTEGER] - [2] 
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [2] as [INTEGER] - [1057] 
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [3] as [BIGINT] - [110] 
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [4] as [VARCHAR] - [new remark] 
21:20:58.194 [main] TRACE o.h.t.d.s.BasicBinder - binding parameter [5] as [VARCHAR] - [152] 

est-il un moyen de résoudre ce , sans créer une entité supplémentaire pour les remarques? J'utilise Hibernate 5.0.12 livré avec Spring Boot 1.5.7. La base de données est postgresql 9.5.6.

+0

Vous mettez donc à jour la valeur de la carte par clé dans une transaction, entraînant une REVTYPE = 2 (DEL) liée à l'ancienne valeur de la clé et une REVTYPE = 0 (ADD) associée à la nouvelle valeur de la clé. – Naros

Répondre

0

J'ai testé cela à la fois contre 5.0.12 et 5.2.10 et dans les deux cas, le schéma de table généré pour votre mapping diffère de ce que vous avez fourni. Est-il possible que ce soit une application héritée que vous avez récemment mise à niveau d'Hibernate?

Par exemple, sur H2 la table créée dans mon test montre les éléments suivants:

create table farm_detail_remark_AUD (
    REV integer not null, 
    field_detail_id integer not null, 
    remark varchar(255) not null, 
    field_id varchar(255) not null, 
    REVTYPE tinyint, 
    primary key (REV, field_detail_id, remark, field_id) 
) 

Par conséquent, pour votre scénario, aucune clé primaire en double peuvent être générés parce que la colonne remark est inclus dans le cadre de la clé primaire index qui évite le problème auquel vous faites face.

+0

ce n'est pas hérité, mais je ne laisse pas hibernate générer le schéma de base de données. Mais c'est un bon conseil pour laisser Hibernate le faire si vous vous perdez. Je vérifierai plus tard ce que renvoie hibernate-versa sur ces entrées "dupliquées" par révision. Savez-vous où cela est documenté? – dve

+0

Nous n'avons aucun endroit spécifique qui décrit ou documente ce que le schéma sera basé sur un mapping donné. Nous nous sommes souvent appuyés sur 'hibernate-tools' où les utilisateurs l'invoquaient pour générer un script de schéma et ils choisissaient d'en exécuter des parties ou, au minimum, de vérifier ce qu'ils avaient créé manuellement. – Naros

+0

Une autre option consiste à lancer votre application contre une base de données fictive ou une instance H2 avec vos mappages d'entités et à consulter les journaux pour voir les instructions DDL qui sont exécutées comme alternative. – Naros