Hibernate使用复合键查找。无效的列名称异常 [英] Hibernate find with composite key. Invalid column name Exception

查看:264
本文介绍了Hibernate使用复合键查找。无效的列名称异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 引起的原因是:使用复合主键进行Hibernate查找,但不断收到以下错误: :org.hibernate.exception.SQLGrammarException:列名称'merchantNumberAccountTypeId'无效。在org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:122)

在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)
在org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
在org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at com.sun.proxy $ Proxy19.executeQuery(Unknown Source)
org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
org.hibernate.loader .Loader.doQuery(Loader.java:829)
在org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
at org。 hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
处org.hibernate.loader.entity.AbstractEntityLoader org.hibernate.loader.Loader.loadEntity(Loader.java:2033)
。 load(AbstractEntityLoader.java:82)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister。 Java的:3720)在org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:458

在org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:427)在org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204)

在org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:260)
在org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:14 8)
在org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1079)
在org.hibernate.internal.SessionImpl.access $ 2200(SessionImpl.java:172)
at org.hibernate.internal.SessionImpl $ IdentifierLoadAccessImpl.load(SessionImpl.java:2425)
位于org.hibernate.internal.SessionImpl.get(SessionImpl.java:975)
位于org.hibernate.ejb。 AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:807)
... 30 more

我可以坚持一个实体没有问题,但不能检索一个(我也试图直接创建一个查询,但我得到同样的问题)。



我的实体类看起来像这样:

  @Entity 
public class MerchantNumberAccountType implements Serializable {

private static final long serialVersionUID = 1L;

@EmbeddedId
私人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;
$ b $ public public MerchantNumberAccountTypeId(){

}

@Override
public boolean equals(Object other){
if(这==其他){
返回true;

if(!(其他instanceof MerchantNumberAccountTypeId)){
return false;
}
MerchantNumberAccountTypeId otherAccTypeId =(MerchantNumberAccountTypeId)other;

返回this.merchantNumber.equals(otherAccTypeId.merchantNumber)&& this.accountType.equals(otherAccTypeId.accountType);


$ b @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;





$ b

更新:

我找到了解决方法。我从@EmbeddedId策略改为@IdClass。但是当我这样做时,EnitityManagerFactory被实例化时出现以下错误 - 由:org.hibernate.DuplicateMappingException引起:表[tblmerchantnumberaccounttype]包含由多个物理列名引用的逻辑列名[accountType]:[id.accountType] ,[identifierMapper.accountType]。为了防止物理列获得id和identifierMapper追加到它们的前面。 (任何人都可以告诉我为什么会发生这种情况?)我注释了accountType&在@Column(value =AccountType)& @Column(value =MerchantNumber)我的Id类中的商户编号,如果你只有@Column而没有value属性,它仍然失败,之后仍然失败,因为现在物理列名在大写字母之前得到并加下划线,即AccountType成为account_type。为了解决这个问题,我可以使用我自己的版本重写ImprovedNamingStrategy中的columnName方法,但不添加下划线,或者我可以简单地使用@Column(值=帐户类型)代替。任何人都可以向我解释这里发生了什么?非常感谢。



更新2:
@EmbeddedId方法也是有效的,重要的是在Key类中注释成员变量并明确地给它们提供列名(不带上限!)。

解决方案
我使用 @PrimaryKeyJoinColumns 解决了这个问题,试试这个(来自另一个例子):

p>

  @ManyToOne 
@PrimaryKeyJoinColumns(value = {
@PrimaryKeyJoinColumn(name =country_code,referencedColumnName = country_code),
@PrimaryKeyJoinColumn(name =zip_code,referencedColumnName =code)
})
private zip zip;

@ManyToOne
@PrimaryKeyJoinColumns(值= {
@PrimaryKeyJoinColumn(名称= COUNTRY_CODE,referencedColumnName = COUNTRY_CODE),
@PrimaryKeyJoinColumn(名称= state_code,referencedColumnName =state_code),
@PrimaryKeyJoinColumn(name =city_name,referencedColumnName =name)
})
私人城市城市;

来自 Hibernate在多个重叠的外键使用的列上抛出AnnotationException


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!).

解决方案

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

这篇关于Hibernate使用复合键查找。无效的列名称异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆