问题
I'm trying to do a Hibernate Find using a composite Primary key but keep getting the following error:
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
I can persist an Entity
with no problems but can't retrieve one (I have also tried to create a query directly but I get the same issue).
My Entity
class looks like this:
@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;
}
}
}
Update:
I've found a workaround for this. I changed from using @EmbeddedId strategy to @IdClass. But when I did this I was getting the following error when the EnitityManagerFactory was being instantiated - Caused by: org.hibernate.DuplicateMappingException: Table [tblmerchantnumberaccounttype] contains logical column name [accountType] referenced by multiple physical column names: [id.accountType], [identifierMapper.accountType]. To prevent the physical columns getting id and identifierMapper appended to the front of them. (Can anyone please tell me why this is happening?) I annotated accountType & merchant number in my Id class with @Column(value="AccountType) & @Column(value="MerchantNumber"), if you just have @Column without the value attribute it still fails. It was still failing after this because now the physical column names were getting and underscore aded before a capital letter. i.e AccountType became account_type. To get around this I can either override the columnName method in ImprovedNamingStrategy with my own version that doesn't add the underscores or I can simply have @Column(value="accounttype") instead. Can anyone explain to me what's going on here? Many thanks.
Update 2: The @EmbeddedId way works too. The important thing annotating the member variables in the Key Class and explicitly giving them the column name (with no caps!).
回答1:
I was getting the same problem. I solved it using the @PrimaryKeyJoinColumns, try this (from another example):
@ManyToOne
@PrimaryKeyJoinColumns(value = {
@PrimaryKeyJoinColumn(name = "country_code", referencedColumnName = "country_code"),
@PrimaryKeyJoinColumn(name = "zip_code", referencedColumnName = "code")
})
private Zip zip;
@ManyToOne
@PrimaryKeyJoinColumns(value = {
@PrimaryKeyJoinColumn(name = "country_code", referencedColumnName = "country_code"),
@PrimaryKeyJoinColumn(name = "state_code", referencedColumnName = "state_code"),
@PrimaryKeyJoinColumn(name = "city_name", referencedColumnName = "name")
})
private City city;
from Hibernate throws AnnotationException on column used by multiple overlapping foreign keys
来源:https://stackoverflow.com/questions/16335513/hibernate-find-with-composite-key-invalid-column-name-exception