org.hibernate.AnnotationException: ссылка внешнего ключа имеет неправильный номер столбца. должно быть 2

Детали таблицы

У меня есть таблицы, как на скриншоте выше

Класс написан как ниже

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

Примечание не добавил геттер и сеттеры

и тестовый код, как показано ниже

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)  

я узнал, что у меня должно быть 2 атрибута в классе FilterAttribute для хранения составного ключа. Но как мы можем это сделать?

4 ответа

Решение
@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 идентификатора составного ключа

ОБНОВЛЕНИЕ: Если он действительно имеет составной первичный ключ с несколькими столбцами, вы должны ссылаться на оба столбца

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

}

Используйте только один @Id в сущности, если вам нужны оба, тогда используйте оба имени столбца

Если вы хотите использовать составной ключ, это не способ сделать это

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

Это что-то вроде этого.. Но по моему опыту эта вещь не самая лучшая и не предлагается использовать даже в спящем режиме, просто найдите другое решение, чтобы использовать ее.. Или использовать его идентификатор

надеюсь, это поможет

Ваша проблема в том, что вы указываете несколько идентификаторов для ваших сущностей. Вам нужно только иметь @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;
}
Другие вопросы по тегам