Hibernate使用复合键查找。列名称异常无效

时间:2013-05-02 10:16:55

标签: java hibernate jpa composite-primary-key

我正在尝试使用复合主键执行Hibernate Find,但不断收到以下错误:

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附加到它们的前面。 (任何人都可以告诉我为什么会这样吗?)我注释了accountType&我的Id类中的商家编号为@Column(value =“AccountType)& @Column(value =”MerchantNumber“),如果你只有@Column没有value属性,它仍然会失败。之后它仍然失败,因为现在物理列名称在大写字母之前得到和下划线。即AccountType变为account_type。为了解决这个问题,我可以使用我自己的版本覆盖ImprovedNamingStrategy中的columnName方法,该版本不添加下划线,或者我可以简单地使用@Column(而不是任何人向我解释这里发生了什么?非常感谢。

更新2: @EmbeddedId方式也有效。重要的是在Key Class中注释成员变量并明确地给它们列名(没有大写!)。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。 我使用 @PrimaryKeyJoinColumns 解决了它,试试这个(来自另一个例子):

{{1}}

来自Hibernate throws AnnotationException on column used by multiple overlapping foreign keys