Я создаю приложение mvc Spring с hibernate и JPA, которому необходимо смоделировать несколько базовых таблиц данных MYSQL, каждая из которых имеет составные ключи с одинаковыми двумя типами данных, поэтому каждая таблица имеет свой собственный составной класс ключей, хотя все составные ключи основаны на тех же двух типах данных с одинаковыми именами свойств. Я получаю ошибку сопоставления hibernate, когда пытаюсь скомпилировать приложение, и мне интересно, может ли это быть из-за того, что спящий режим не может сравнивать различные классы первичных ключей. Может ли кто-нибудь показать мне, как исправить это, чтобы мое приложение скомпилировалось?
Вот часть моего класса Description
которая устанавливает отношения ManyToOne
между классами Description
и Concept
на основе их соответствующих составных классов первичного ключа:
@ManyToOne
@JoinColumn(name="descriptionPK", referencedColumnName = "conceptPK")
private Concept concept;
Вот ошибка, которую я получаю:
Caused by: org.hibernate.MappingException:
Unable to find column with logical name:
conceptPK in org.hibernate.mapping.Table(sct2_concept) and its related supertables and secondary tables
Код для ConceptPK
:
@Embeddable
class ConceptPK implements Serializable {
@Column(name="id", nullable=false)
protected BigInteger id;
@Column(name="effectiveTime", nullable=false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime effectiveTime;
public ConceptPK() {}
public ConceptPK(BigInteger bint, DateTime dt) {
this.id = bint;
this.effectiveTime = dt;
}
/** getters and setters **/
public DateTime getEffectiveTime(){return effectiveTime;}
public void setEffectiveTime(DateTime ad){effectiveTime=ad;}
public void setId(BigInteger id) {this.id = id;}
public BigInteger getId() {return id;}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final ConceptPK other = (ConceptPK) obj;
if (effectiveTime == null) {
if (other.effectiveTime != null) return false;
} else if (!effectiveTime.equals(other.effectiveTime)) return false;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
return hash;
}
}
Код для DescriptionPK
:
@Embeddable
class DescriptionPK implements Serializable {
@Column(name="id", nullable=false)
protected BigInteger id;
@Column(name="effectiveTime", nullable=false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime effectiveTime;
public DescriptionPK() {}
public DescriptionPK(BigInteger bint, DateTime dt) {
this.id = bint;
this.effectiveTime = dt;
}
/** getters and setters **/
public DateTime getEffectiveTime(){return effectiveTime;}
public void setEffectiveTime(DateTime ad){effectiveTime=ad;}
public void setId(BigInteger id) {this.id = id;}
public BigInteger getId() {return id;}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final DescriptionPK other = (DescriptionPK) obj;
if (effectiveTime == null) {
if (other.effectiveTime != null) return false;
} else if (!effectiveTime.equals(other.effectiveTime)) return false;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
return hash;
}
}
Вам нужно изменить аннотацию @ManyToOne, чтобы использовать несколько столбцов, как показано ниже, а также вам не нужно создавать дубликаты двух встраиваемых классов ConceptPK и DescriptionPK, если все свойства одинаковы, просто создайте один EmbeddablePK и используйте в обоих объектах.
@OneToMany(mappedBy = "concept", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
public List<Description> descriptions = new LinkedList<Description>();
И класс описания:
@ManyToOne
@JoinColumns({ @JoinColumn(name = "A_COLUMN", referencedColumnName = "A_COLUMN", insertable = false, updatable = false),
@JoinColumn(name = "B_COLUMN", referencedColumnName = "B_COLUMN", insertable = false, updatable = false),
})
public Concept concept;
MyPrimaryKey
ниже, вы можете иметь один встраиваемыйMyPrimaryKey
и использовать его в обеих сущностях. @Embeddable открытый класс MyPrimaryKey реализует Serializable {... @EmbeddedId private MyPrimaryKey myPrimaryKey; @EmbeddedId private MyPrimaryKey myPrimaryKey;