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