org.hibernate.AnnotationException:外键引用的列数错误。应该是2

时间:2014-06-05 05:53:47

标签: java hibernate hibernate-mapping hibernate-annotations

Table details

我有如上面屏幕截图中的表格

类编写如下

@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个属性来保存复合键。但是我们怎么能这样做呢?

4 个答案:

答案 0 :(得分:10)

@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个ID复合键

更新:如果它确实有复合多列主键,则应引用两列

答案 1 :(得分:0)

您的问题是您为实体指定了多个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;
}

答案 2 :(得分:0)

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

@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

希望有所帮助

答案 3 :(得分:0)

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

}

如果您需要两个@Id,请在实体中仅使用一个@Id,然后同时使用列名