1

I'm using hibernate-entitymanager in a Spring application. I'm in the process of upgrading my Hibernate version. Narrowed it down to the exact version: when I upgrade from 4.2.1.Final to 4.2.2.Final (or anything higher than that), I'm getting the following error when my unit tests starts up and try to create the database schema:

2014-03-02 18:02:51,559 ERROR [SchemaExport] [main] HHH000389: Unsuccessful: alter table Incident add constraint FK_d91dua6gkdp1jn826adqss3aq foreign key (uuid) references Incident
2014-03-02 18:02:51,559 ERROR [SchemaExport] [main] Constraint "FK_D91DUA6GKDP1JN826ADQSS3AQ" already exists; SQL statement:

    alter table Incident
        add constraint FK_d91dua6gkdp1jn826adqss3aq
        foreign key (uuid)
        references Incident [90045-170]

The error does not prevent the system from working just fine, but clearly I can't go to production with such a nasty error in my system and no explanation of it.

This looks a lot like the Incident table has a foreign key relationship to itself, which is absolutely not the case.

I'll try to copy the essence here of the Incident entity:

@Entity
@Audited
@EntityListeners(value = {IncidentIdentifierPrePersistListener.class })
@FilterDefs( ... )
@Filters( ... )
public class Incident extends SomeBaseClass {

    @Id
    private String uuid = UUID.randomUUID().toString();

    @Column(nullable = false, unique = true)
    private long identifier;

    ... a bunch more fields ...
}

Please let me know if I can provide anything else to help ya'all to shed a light on this. I've played around with it for hours, fruitless, and your help would be much appreciated.

Sander Verhagen
  • 8,540
  • 4
  • 41
  • 63
  • So your app does need to perform schema export each time it loads? – gerrytan Mar 03 '14 at 02:23
  • No, unit tests do (H2 in-memory database). Production will only use schema generation to validate the schema, and I've not seen any problems there. But errors in unit tests are a reason for concern. And as long as I don't understand these errors, I also won't just assume that nothing will go wrong in production. I'm upgrading Hibernate and this is a red flag for me. – Sander Verhagen Mar 03 '14 at 02:48
  • 2
    Can you try removing `unique = true` from uuid? It is redundant given the field is already being marked with `@Id` don't you think? – gerrytan Mar 03 '14 at 02:56
  • That is a good observation, and I tinkered with it before, but reverted the change because it didn't make a difference. I'll remove it from the question, for clarity. – Sander Verhagen Mar 03 '14 at 03:12
  • 1
    Ok, I think it's hard to debug. I recommend you create a minimal project to reproduce the problem, upload it to github so rest of us can test it – gerrytan Mar 03 '14 at 03:45

1 Answers1

2

Here is what happened:

  • Incident defined a @ManyToOne to an entity Project
  • Project incorrectly defined a @ManyToMany back to the entity Incident (should have been a @OneToMany)
  • As a result Hibernate generated the awkward following constraint:

    CONSTRAINT fk909a8f241708a1e FOREIGN KEY (uuid)
      REFERENCES incident (uuid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
    
  • Incident inherits SomeBaseClass which has @Inheritance(strategy = InheritanceType.JOINED)

  • As a result Hibernate generated the following constraint:

    CONSTRAINT fk909a8f2ddd08e84 FOREIGN KEY (uuid)
      REFERENCES somebaseclass (uuid) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
    
  • As a result of HHH-8217 (Make generated constraint names short and non-random) in Hibernate 4.2.2 the above two constraint definitions suddenly got the same name (Hibernate did only consider the entity and the columns of the foreign key constraint, not the target entity of the foreign key; note how generateName only takes one Table as a parameter)

  • And there was the corresponding clash: Constraint ... already exists

Changing the @ManyToMany to @OneToMany fixes this entirely.

By the way, the offending field definition (the one with the @ManyToMany) also previously caused me problems with Hibernate Envers' @Audited, the reason of which I never understood, and that got resolved now as well. It's a good day. (Not sure if @Audited means much for a mapped field, but at least I can have @Audited on the class without needing to deal with this field.)

Sander Verhagen
  • 8,540
  • 4
  • 41
  • 63