Narrow the derived identity boot rejection to associations that do not own their columns

XMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: Model
    • None
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      The boot guard forbidDerivedIdentity in MongoAdditionalMappingContributor detects derived identity by finding an entity-level ToOne whose column name(s) overlap the identifier's column names. That predicate also rejects a plain, writable association whose join column happens to be named the same as the id column, for example:

      @Entity
      class ItemA {
          @Id
          int id;
      
          @ManyToOne
          @JoinColumn(name = "id")
          ItemB itemB;
      }
      

      That mapping works in MongoDB. The guard runs before setIdentifierColumnName, so it compares pre-rename SQL column names. After the rename the identifier's column is _id and the association's column is still id; they are distinct Column instances, both fields are written on insert, and a $lookup on localField: "id" resolves correctly. This shape was exercised by a passing integration test before the guard was added.

      Consider narrowing the predicate so it rejects only an association that does not own its columns.

      Proposed discriminator

      Measured on Hibernate ORM 7.4.5 by dumping the mapping model for each shape at boot:

      mapping column-name overlap with id association column insertable/updatable
      plain @ManyToOne @JoinColumn(name = "id") yes true / true
      @MapsId with @EmbeddedId yes false / false
      @MapsId with a simple @Id yes false / false
      @JoinColumn(name = "id", insertable = false, updatable = false) yes false / false
      @OneToOne @PrimaryKeyJoinColumn association has no columns n/a

      In every shape the association's Column is a distinct instance from the identifier's and is not registered in the table, so instance identity does not discriminate. Column insertability does: when the association does not own its columns, nothing ever writes that field, so after the identifier is renamed to _id the field never exists and a $lookup on it silently matches nothing. That is the case that must keep failing at boot. When the association owns its column, the two mappings resolve to separate BSON fields and translation is correct.

      Second gap in the same predicate

      @OneToOne @PrimaryKeyJoinColumn yields a ToOne with zero columns, so the overlap predicate never fires on it. Whether that shape translates correctly or breaks silently has not been determined.

      Context

      HIBERNATE-207 added the guard. The over-broad predicate was found when the guard broke the many-to-one join test added by HIBERNATE-223, whose entity used @JoinColumn(name = "id"); that test was fixed by renaming its join column, so nothing is currently blocked.

            Assignee:
            Unassigned
            Reporter:
            Jeffrey Yemin
            None
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: