starnowski / posmulten-hibernate

Integration of Posmulten and Hibernate libraries

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add functionality that optionaly creates foreignKey constraint for OneToOne and OneToMany relation that use JoinColumnsOrFormulas annotation

starnowski opened this issue · comments

Hibernate does not allow for overlapping foreign keys https://hibernate.atlassian.net/browse/HHH-6221.
Because of this issue it is harder to generate database schema where foreign keys shares tenant id column with primary key and other foreign keys.
For below example we have two tables:
The user_info_nonforeignkeyconstraint table can have multiple references to posts table.

create table user_info_nonforeignkeyconstraint (
       user_id varchar(255) not null,
        tenant varchar(255) not null,
        password varchar(255),
        username varchar(255),
        primary key (user_id, tenant)
    )
create table posts_nonforeignkeyconstraint (
       key int8 not null,
        tenant_id varchar(255) not null,
        text text,
        user_id varchar(255),
        primary key (key, tenant_id)
    )

To map these tables into java model and having issue "Mixing insertable and non insertable columns in a property is not allowed" we need to use JoinColumnsOrFormulas annotation.

@Table(name = "user_info_nonforeignkeyconstraint")
@ToString(of = {"primaryKey", "username"})

public class User {

    @EmbeddedId
    @AttributeOverride(name = "stringKey", column = @Column(name = "user_id"))
    @AttributeOverride(name = "tenant", column = @Column(name = "tenant", insertable = false, updatable = false))
    private StringPrimaryKey primaryKey;
    private String username;
    private String password;

    @OneToMany(mappedBy = "author", fetch = LAZY)
    @JoinColumnsOrFormulas(value = {
            //name --> Post column, referencedColumnName -- User column
            @JoinColumnOrFormula(column = @JoinColumn(name = "tenant_id", referencedColumnName = "tenant")),
            @JoinColumnOrFormula(column = @JoinColumn(name = "user_id", referencedColumnName = "user_id"))
    })
    private Set<Post> posts;
}
@Table(name = "posts_nonforeignkeyconstraint")
@IdClass(LongPrimaryKey.class)

public class Post {

    @Id
    @GeneratedValue
    private long key;
    @Id
    @Column(name = "tenant_id", insertable = false, updatable = false)
    private String tenant;

    @ManyToOne
    @JoinColumnsOrFormulas(value = {
            @JoinColumnOrFormula(formula = @JoinFormula(value = "tenant_id", referencedColumnName = "tenant")),
            @JoinColumnOrFormula(column = @JoinColumn(name = "user_id", referencedColumnName = "user_id"))
    })
    private User author;

    @Column(columnDefinition = "text")
    private String text;
}
@Embeddable

public class StringPrimaryKey implements Serializable {

    private String stringKey;

    private String tenant;

//Setters, Getters, equals and hashCode

The problem with this approach is that Hibernate does not generate foreign key in posts_nonforeignkeyconstraint to user_info_nonforeignkeyconstraint table. Developer needs to for test purpose add this statement in import.sql file.

ALTER TABLE posts_nonforeignkeyconstraint ADD CONSTRAINT fk_posts_users_author_manual_added FOREIGN KEY (user_id, tenant_id) REFERENCES user_info_nonforeignkeyconstraint;

The goal is to add feature that will lookup for such *annotation combination (activated by a property) or with specified annotation for property and generate foreign key based on tenant column and column that reference to other table.

    • JoinColumnsOrFormulas plus ManyToOne or OneToOne

Blocked by: starnowski/posmulten#252

Consider adding two annotations:

  • IgnoreForeignKeyCreation // In case when the foreign key is by default created
  • ForeignKeyCreation
    table = table name (optional) // It would be used in the case when implementation would create a foreign key for the wrong table.
    schema = schema name (optional)
    tenantColumnReference = name of tenant column for reference table (optional)
    columnsReference = array of objects JoinColumn()