我正在尝试使用复合主键进行休眠查找,但不断收到以下错误:
Caused by: org.hibernate.exception.SQLGrammarException: Invalid column name 'merchantNumberAccountTypeId'.
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:122)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at com.sun.proxy.$Proxy19.executeQuery(Unknown Source)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:829)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2033)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3720)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:458)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:427)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:260)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1079)
at org.hibernate.internal.SessionImpl.access$2200(SessionImpl.java:172)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2425)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:807)
... 30 more
我可以毫无问题地坚持一个Entity
但无法检索一个(我也尝试直接创建一个查询,但我遇到了同样的问题)。
我的Entity
课看起来像这样:
@Entity
public class MerchantNumberAccountType implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private MerchantNumberAccountTypeId merchantNumberAccountTypeId;
public MerchantNumberAccountTypeId getMerchantNumberAccountTypeId() {
return merchantNumberAccountTypeId;
}
public void setMerchantNumberAccountTypeId(MerchantNumberAccountTypeId merchantNumberAccountTypeId) {
this.merchantNumberAccountTypeId = merchantNumberAccountTypeId;
}
@Embeddable
public static class MerchantNumberAccountTypeId implements Serializable {
private static final long serialVersionUID = 1L;
@Column
public String merchantNumber;
@Column
public String accountType;
public MerchantNumberAccountTypeId(){
}
@Override
public boolean equals(Object other){
if(this == other){
return true;
}
if (!(other instanceof MerchantNumberAccountTypeId)) {
return false;
}
MerchantNumberAccountTypeId otherAccTypeId = (MerchantNumberAccountTypeId) other;
return this.merchantNumber.equals(otherAccTypeId.merchantNumber) && this.accountType.equals(otherAccTypeId.accountType);
}
@Override
public int hashCode(){
return merchantNumber.hashCode() + accountType.hashCode();
}
public String getMerchantNumber() {
return merchantNumber;
}
public void setMerchantNumber(String merchantNumber) {
this.merchantNumber = merchantNumber;
}
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
}
}
更新:
我找到了解决方法。我从使用@EmbeddedId 策略更改为@IdClass。但是当我这样做时,我在实例化 EnitityManagerFactory 时收到以下错误 - 原因:org.hibernate.DuplicateMappingException:表 [tblmerchantnumberaccounttype] 包含多个物理列名引用的逻辑列名 [accountType]:[id.accountType] , [identifierMapper.accountType]。防止物理列将 id 和 identifierMapper 附加到它们的前面。(谁能告诉我为什么会这样?)如果您只有 @Column 而没有value 属性它仍然失败。在此之后它仍然失败,因为现在物理列名在大写字母前加了下划线。即AccountType 变成account_type。为了解决这个问题,我可以使用我自己的不添加下划线的版本覆盖 ImprovementNamingStrategy 中的 columnName 方法,或者我可以简单地使用 @Column(value="accounttype") 。谁能向我解释这里发生了什么?非常感谢。
更新 2: @EmbeddedId 方式也有效。重要的是在 Key Class 中注释成员变量并显式地给它们列名(没有大写!)。