Hibernate:将一对多引用从非主键映射到主键

Hibernate: Mapping a One-To-Many-Reference from a non primary key to a primary key

我有一个遗留数据库,其中(不幸的是)很少放置外键。如果我在 java 中创建自己的外键(列 A.testnr 指向 B.nummer),hibernate 正在使用 A 的主键(列 id),这会(如预期)导致错误。

我读到我必须在 class B 的列上放置一个 mappedBy-Reference。 class B 中的主键是一个数字,我试图将它更改为一个 Set( A)但是我得到了一些持久性错误。

映射多对一关系 - A.testnr -> B.nummer

Class A    

@Id
@Column(name = "NUMMER", unique = true, nullable = false, precision = 22, 
scale = 0)
public BigDecimal getNummer() {
 return this.nummer;
}

public void setNummer(BigDecimal nummer) {
  this.nummer = nummer;
 }

@ManyToOne
@JoinColumn(name = "nummer", referencedColumnName = "nummer")
public B getTestnr() {
  return this.testnr;
}

public void setTestnr(B testnr) {
  this.testnr = testnr;
}


Class B

@Id
@Column(name = "NUMMER", unique = true, nullable = false, precision = 22, 
  scale = 0) 
public BigDecimal getNummer() {
  return this.nummer;
}

public void setNummer(BigDecimal nummer) {
  this.nummer = nummer;
}

错误消息:javax.persistence.EntityNotFoundException 因为 A (A.nummer) 中的主键不是 B.nummer.

的一部分,这是可以理解的

正如我已经说过的,我尝试使用 MappedBy-Reference 并将 class B 中的 BigDecimal PK 更改为 Set(A)。

@Id
@OneToMany(fetch = FetchType.EAGER, mappedBy = "testnr")
@Column(name = "NUMMER", unique = true, nullable = false, precision = 22, 
 scale = 0)
public Set<A> getNummern() {
  return this.nummern;
}

public void setNummern(Set<A> nummern) {
  this.nummern = nummern;
}

通过此更改,我收到运行时错误可能是由于持久层中的差异。

我的目标是将一个非主键映射到另一个 class 的主键甚至可以使用休眠,还是在这种情况下我被迫使用本机 sql?

In order for you to make a join on a non-indexed column, that's absolutely right, you have to use referencedColumnName. However in your second code snipped you marked your @ManyToOne collection as id, which is incorrect. If I understood you correctly, multiple A.nummer belong to a single B.testnr.

这就是您得到想要的东西的方式:

Class A, nummer which belongs to testnr.

@Entity
@Table(name = "a_table")
public class A {

    @Id // a_table_id
    @Column(name = "NUMMER", unique = true, nullable = false, precision = 22)
    private BigDecimal nummer;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "nummer", referencedColumnName = "nummer")
    // make sure referenced column name matches column in table B
    private B testnr;

    public BigDecimal getNummer() {
        return this.nummer;
    }

    public void setNummer(BigDecimal nummer) {
        this.nummer = nummer;
    }

    public B getTestnr() {
        return this.testnr;
    }

    public void setTestnr(B testnr) {
        this.testnr = testnr;
    }

}

Class B, testnr that has multiple nummers.

@Entity
@Table(name = "b_table")
public class B {

    @Id // b_table_id
    @Column(name = "b_table_id")
    private BigDecimal testnr;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "testnr")
    private Set<A> nummern;

    public Set<A> getNummern() {
        return this.nummern;
    }

    public void setNummern(Set<A> nummern) {
        this.nummern = nummern;
    }
}