chiranjeevigk
chiranjeevigk

Reputation: 1666

org.hibernate.AnnotationException: A Foreign key refering has the wrong number of column. should be 2

Table details

I have the tables as in the screenshot above

Class are written as below

@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;  
} 

Note not added getter and setters

and test code as below

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());  
            }  
        }  

I am getting the below exception

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)  

i came to know i should have the 2 attributes in FilterAttribute class to hold the composite key.. But how can we do that?

Upvotes: 11

Views: 22690

Answers (4)

StanislavL
StanislavL

Reputation: 57381

@Entity  
public class ObjectAttribute {  
    @Id  
    private int id;  
    @Id  <------------------------ try to remove this annotation
    @ManyToOne  
    @JoinColumn(name="objectId")  
    private Object object;  
    private String name;  
}  

It thinks your ObjectAttribute has 2 ids compound key

UPDATE: If it really has compound multi column primary key you should reference both columns

Upvotes: 14

Kunwar Babu
Kunwar Babu

Reputation: 45

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

}

Use only one @Id in entity if you need both then use both the columns name

Upvotes: 0

Aviad
Aviad

Reputation: 1549

If you would like to use composite key this is not the way to do it

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

You have 2 times tag @id, So you need to remove of create composite key with @IdClass annotation if you would like that(not suggested).

You need to create class that contain 2 keys that will hold composite key

public class CompositeKey {
    private int id; 
    private Object object;  

    //getters and setter
}

After that you will define the key in your entity

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

This is something like that.. But from my experience this thing is not the best things and not suggested to use even by hibernate, Just find another solution to use it.. Or to use his id

Hope that helps

Upvotes: 0

JamesENL
JamesENL

Reputation: 6540

Your problem is that you are specifying multiple ID's for your entities. You only need to have the @Id annotation on the field that represents the object's primary key. By annotating fields with @ManyToOne or @OneToMany Hibernate will treat that field as a foreign key without you having to do anything. If you remove the extra @Id fields, everthing should start working.

@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;
}

Upvotes: 0

Related Questions