Hibernate how to use a constant as part of composi

2019-02-24 06:38发布

问题:

I have a master table A with a composite primary key, consisting of two columns. One of these columns is a constant ("THE CONSTANT VALUE" in the code below). This table definition looks like the following:

@Entity public class Master {
  @Id
  @Column(name = "SIGNIFICANT_KEY")
  private String realKey;

  @Id
  @Column(name = "CONSTANT_KEY")
  private String constantPartKey;
}

I have a detail table B, referencing master table A using only one (non-constant) column. I want to implement usual ManyToOne and OneToMany relations between the two tables.

Question: How can I handle this situation with Hibernate?

The only solution for master reference I found relies on using formulas:

@Entity public class Detail {
  @ManyToOne
  @JoinColumnsOrFormulas(value={
    @JoinColumnOrFormula(column=
      @JoinColumn(name = "SIGNIFICANT_KEY",
                  referencedColumnName = "SIGNIFICANT_KEY",
                  insertable=false, updatable=false, nullable = false)),
    @JoinColumnOrFormula(formula=
      @JoinFormula(referencedColumnName="CONSTANT_KEY", value="'THE CONSTANT VALUE'"))
  })
  Master master;
}

Now I see other problem: I cannot use this field in OneToMany relation due to the java.lang.ClassCastException problem I've reported here earlier: https://hibernate.onjira.com/browse/HHH-6811

回答1:

I really wonder how it can be helpful to have a constant column value in a database, but anyway...

What I would do is to only map the non-constant column as ID, and make the constant column a regular column, with a constant value:

@Entity
public class Strange {
    @Id
    private Long id;

    @Column
    private long constant = 345; // the constant that you want in your database

    @OneToMany(mappedBy = "strange")
    private Set<Detail> details;

    ...
    // no setter for constant!
}

@Entity
public class Detail {
   ...
   @ManyToOne
   @JoinColumn(name = "strange_id")
   private Strange strange;
}

If other entities reference this same Strange entity using its full composite key, then simply do the following:

@Entity
public class Strange {
    @Id
    @Column(name = "strange_id")
    private Long id;

    @Id
    private long constant = 345; // the constant that you want in your database

    @OneToMany(mappedBy = "strange")
    private Set<Detail> details;

    ...
    // no setter for constant!
}

@Entity
public class Detail {
   ...
   @ManyToOne
   @JoinColumn(name = "strange_id", referencedColumnName = "strange_id")
   private Strange strange;
}

You can reference other entities using something other than their PK. Another unique column is also OK. And since strange_id is unique, it fits the bill. The referencedColumnName attribute must be used to specify the referenced column name, in that case.