【问题标题】:org.hibernate.AnnotationException: A Foreign key refering has the wrong number of column. should be 2org.hibernate.AnnotationException:外键引用的列数错误。应该是 2
【发布时间】:2014-07-25 23:56:06
【问题描述】:

我有上面截图中的表格

类的写法如下

@Entity  
public class Object {  
    @Id  
    private int id;  

    private String name;  

    @OneToMany(mappedBy="object",fetch=FetchType.LAZY)  
    private List<ObjectAttribute> attrubuteList;  
}  

@Entity  
public class ObjectAttribute {  
    @Id  
    private int id;  
    @Id  
    @ManyToOne  
    @JoinColumn(name="objectId")  
    private Object object;  
    private String name;  
}  

@Entity  
public class Filter {  
    @Id  
    private int filterId;  
    @ManyToOne  
    @JoinColumn(name="ObjectId")  
    private Object object;  
    private String filterName;  
    @OneToMany(mappedBy="filter")  
    private Set<FilterAttribute> filterValues;  
}  

@Entity  
public class FilterAttribute implements Serializable {  

    @Id  
    private int filterAttrId;  
    @Id  
    @ManyToOne  
    @JoinColumn(name="objectId")  
    private Object object;  
    @Id  
    @ManyToOne  
    @JoinColumn(name="filterId")  
    private Filter filter;  
    @Id  
    @ManyToOne  
    @JoinColumn(name="attributeId")  
    private ObjectAttribute attribute;  

    private String value;  
} 

注意没有添加getter和setter

测试代码如下

List<Object> list = sess.createCriteria(Object.class).list();  
        for(Object ob: list)  
        {  
            System.out.println("Object name : "+ ob.getName());  
            List<ObjectAttribute> attList = ob.getAttrubuteList();  

            for (Iterator iterator = attList.iterator(); iterator.hasNext();) {  
                ObjectAttribute objectAttribute = (ObjectAttribute) iterator  
                        .next();  
                System.out.println(objectAttribute.getName());  
            }  
        }  

我得到以下异常

Caused by: org.hibernate.AnnotationException: A Foreign key refering test.rest.ObjectAttribute from test.rest.FilterAttribute has the wrong number of column. should be 2  
    at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:450)  

我知道我应该在 FilterAttribute 类中拥有 2 个属性来保存复合键。但是我们该怎么做呢?

【问题讨论】:

    标签: java hibernate hibernate-mapping hibernate-annotations


    【解决方案1】:
    @Entity  
    public class ObjectAttribute {  
        @Id  
        private int id;  
        @Id  <------------------------ try to remove this annotation
        @ManyToOne  
        @JoinColumn(name="objectId")  
        private Object object;  
        private String name;  
    }  
    

    它认为你的 ObjectAttribute 有 2 个 ids 复合键

    更新:如果它真的有复合多列主键,你应该引用两列

    【讨论】:

    • 如果我删除了我还有另一个问题stackoverflow.com/questions/24044130/…
    • 我会添加一个单独的 id 列作为 ObjectAttribute 的主键,并且所有引用都应该是通常的外键。
    • 我没有从您的图片中看到单个 id 主键
    • 我发现了问题..正如你所建议的,我已经删除了对象变量的 ObjectAttribute 中的@Id..如果运行良好,代码..但是对于我添加的另一个问题评论..因为我没有设置这些codeobj.getAttrubuteList().add(depAtt); obj.getAttrubuteList().add(attName); obj.getAttrubuteList().add(ageAtt);code 你能告诉我为什么我们需要这样做吗?
    【解决方案2】:

    您的问题是您为实体指定了多个 ID。您只需要在表示对象主键的字段上添加@Id 注释即可。通过使用@ManyToOne@OneToMany 注释字段,Hibernate 会将该字段视为外键,而您无需执行任何操作。如果您删除额外的 @Id 字段,一切都应该开始工作了。

    @Entity  
    public class Object {  
        @Id  
        private int id;  
    
        private String name;  
    
        @OneToMany(mappedBy="object",fetch=FetchType.LAZY)  
        private List<ObjectAttribute> attrubuteList;  
    }  
    
    @Entity  
    public class ObjectAttribute {  
        @Id  
        private int id;  
    
        @ManyToOne  
        @JoinColumn(name="objectId")  
        private Object object;  
    
        private String name;  
    }  
    
    @Entity  
    public class Filter {  
        @Id  
        private int filterId;  
    
        private String filterName;  
    
        @ManyToOne  
        @JoinColumn(name="ObjectId")  
        private Object object;          
    
        @OneToMany(mappedBy="filter")  
        private Set<FilterAttribute> filterValues;  
    }  
    
    @Entity  
    public class FilterAttribute implements Serializable {  
        @Id  
        private int filterAttrId;  
    
        @ManyToOne  
        @JoinColumn(name="objectId")  
        private Object object;  
    
        @ManyToOne  
        @JoinColumn(name="filterId")  
        private Filter filter;  
    
        @ManyToOne  
        @JoinColumn(name="attributeId")  
        private ObjectAttribute attribute;
    }
    

    【讨论】:

      【解决方案3】:

      如果您想使用复合键,这不是这样做的方法

      @Entity  
      public class ObjectAttribute {  
          @Id  
          private int id;  
          @Id  
          @ManyToOne  
          @JoinColumn(name="objectId")  
          private Object object;  
          private String name;  
      }
      

      您有 2 次标记 @id,因此如果您愿意,您需要删除带有 @IdClass 注释的创建复合键(不建议)。

      您需要创建包含 2 个键来保存复合键的类

      public class CompositeKey {
          private int id; 
          private Object object;  
      
          //getters and setter
      }
      

      之后,您将在实体中定义键

      @Entity  
      @IdClass(CompositeKey.class)
      public class ObjectAttribute {  
          @Id  
          private int id;  
          @Id  
          @ManyToOne  
          @JoinColumn(name="objectId")  
          private Object object;  
          private String name;  
      }
      

      这是类似的东西..但是根据我的经验,这不是最好的东西,甚至不建议使用hibernate,只需找到另一个解决方案来使用它..或者使用他的id

      希望有帮助

      【讨论】:

        【解决方案4】:
        @Entity  
        public class ObjectAttribute {  
        @Id  
        private int id;  
        @Id  
        @ManyToOne  
        @JoinColumn(name="objectId")  
        private Object object;  
        private String name;  
        

        }

        如果你需要两个@Id,则在实体中只使用一个@Id,然后使用两个列名

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-09-11
          • 2015-01-28
          • 1970-01-01
          • 2014-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-25
          相关资源
          最近更新 更多