Внешний ключ, ссылающийся на Triple из аннотации, имеет неправильное количество столбцов.

#java #hibernate

#java #переход в спящий режим

Вопрос:

Хотя я провел небольшое исследование по этому вопросу и обнаружил множество угроз, открытых в Интернете, я не смог решить свою проблему. Я прилагаю свой код:

Triple.java первичный ключ создается 3 URI из трех разных концепций, но это один и тот же столбец (это проблема?)

         @Entity
        @IdClass(ConceptPk.class)
        @Table(name = "triple")
        public class TripleDBModel {

            protected List<Annotation> annotations;
            public String conceptUriSubject;
            public String conceptUriObject;
            public String conceptUriPredicate;
            public String id;



            @ManyToMany(
                    cascade={CascadeType.ALL},  
                    fetch=FetchType.LAZY
            )   
            @JoinTable(name = "triple_has_annotation", 
                    joinColumns=@JoinColumn(name="annotation_id"),
                    inverseJoinColumns={@JoinColumn(name="uri_concept_subject", referencedColumnName="triple_id"), @JoinColumn(name="uri_concept_object", referencedColumnName="triple_id"), @JoinColumn(name="uri_concept_predicate", referencedColumnName="triple_id")
         })//EDIT
            public List<Annotation> getAnnotations() {
                return annotations;
            }
            public void setAnnotations(List<Annotation> annotations) {
                this.annotations = annotations;
            }
            @Id 
            @Column(name = "uri_concept_subject", length = 100)
            public String getConceptUriSubject() {
                return conceptUriSubject;
            }
            public void setConceptUriSubject(String conceptUriSubject) {
                this.conceptUriSubject = conceptUriSubject;
            }
            @Id 
            @Column(name = "uri_concept_object", length = 100)
            public String getConceptUriObject() {
                return conceptUriObject;
            }
            public void setConceptUriObject(String conceptUriObject) {
                this.conceptUriObject = conceptUriObject;
            }
            @Id 
            @Column(name = "uri_concept_predicate", length = 100)
            public String getConceptUriPredicate() {
                return conceptUriPredicate;
            }
            public void setConceptUriPredicate(String conceptUriPredicate) {
                this.conceptUriPredicate = conceptUriPredicate;
            }

 @Id
        @Column(name = "triple_id", unique = true, nullable = false)
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
    }  
  

ConceptPk.java

     @Embeddable
    public class ConceptPk implements java.io.Serializable {

        private static final long serialVersionUID = 1L;
        public String conceptUriSubject;
        public String conceptUriObject;
        public String conceptUriPredicate;

        @Id
        @Column(name = "uri", length = 100, unique = true, nullable = false)
        public String getConceptUriSubject() {
            return conceptUriSubject;
        }
        public void setConceptUriSubject(String conceptUriSubject) {
            this.conceptUriSubject = conceptUriSubject;
        }

        @Id
        @Column(name = "uri", length = 100, unique = true, nullable = false)
        public String getConceptUriObject() {
            return conceptUriObject;
        }
        public void setConceptUriObject(String conceptUriObject) {
            this.conceptUriObject = conceptUriObject;
        }

        @Id
        @Column(name = "uri", length = 100, unique = true, nullable = false)
        public String getConceptUriPredicate() {
            return conceptUriPredicate;
        }
        public void setConceptUriPredicate(String conceptUriPredicate) {
            this.conceptUriPredicate = conceptUriPredicate;
        }
  

Annotation.java

     @Entity
    @Table(name = "annotations")
    public class Annotation {

        private Integer id;
        private List<TripleDBModel> triples;  

    @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "annotation_id", unique = true, nullable = false)
        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

    @ManyToMany(
                cascade={CascadeType.ALL},
                mappedBy = "annotations", //EDIT
                fetch=FetchType.LAZY
        )   
        public List<TripleDBModel> getTriples() {
            return triples;
        }

        public void setTriples(List<TripleDBModel> triples) {
            this.triples = triples;
        }
  

Но я получаю эту ошибку:

 Caused by: org.hibernate.AnnotationException: A Foreign key refering TripleDBModel from Annotation has the wrong number of column. should be 3
  

Что я делаю не так?? Заранее спасибо

Комментарии:

1. Почему вы присвоили имени столбца для всех 3 столбцов id в ConceptPK значение «uri»? Они должны быть разными, иначе они указывали бы на один и тот же столбец.

2. Поскольку первичный ключ представляет собой комбинацию 3 понятий, то 3 из них должны указывать на uri, идентификатор понятия

3. Вам все равно придется ссылаться на 3 разных столбца в наборе данных. Вы не можете заставить несколько наборов данных определять внешний ключ для 4-го. Внешний ключ определен в Tripple таблице, и я сомневаюсь, что в нем есть столбец uri , не так ли?

4. Я отредактировал свой вопрос, поле annotation_id находится не в Triple, а в Annotation. Первичный ключ Triple состоит из 3 annotation_id, состоящих из 3 разных аннотаций. annotation_id это имя поля в базе данных id . Это правильно?

5. Я добавил triple_id в качестве идентификатора Triple, что вы имели в виду??

Ответ №1:

Окончательное решение таково:

ConceptPk.java

 @Embeddable
public class ConceptPk implements java.io.Serializable {

    private static final long serialVersionUID = 1L;
    public Concept conceptUriSubject;
    public Concept conceptUriObject;
    public Concept conceptUriPredicate;

    @Id 
    @ManyToOne(cascade=CascadeType.MERGE)
    @JoinColumn(name="uri_concept_subject")
    public Concept getConceptUriSubject() {
        return conceptUriSubject;
    }
    public void setConceptUriSubject(Concept conceptUriSubject) {
        this.conceptUriSubject = conceptUriSubject;
    }

    @Id 
    @ManyToOne(cascade=CascadeType.MERGE)
    @JoinColumn(name="uri_concept_object")
    public Concept getConceptUriObject() {
        return conceptUriObject;
    }
    public void setConceptUriObject(Concept conceptUriObject) {
        this.conceptUriObject = conceptUriObject;
    }

    @Id 
    @ManyToOne(cascade=CascadeType.MERGE)
    @JoinColumn(name="uri_concept_predicate")
    public Concept getConceptUriPredicate() {
        return conceptUriPredicate;
    }
    public void setConceptUriPredicate(Concept conceptUriPredicate) {
        this.conceptUriPredicate = conceptUriPredicate;
    }
  

Triple.java

 @Entity
@IdClass(ConceptPk.class)
@Table(name = "triple")
public class TripleDBModel {

    protected List<Annotation> annotations;
    public Concept conceptUriSubject;
    public Concept conceptUriObject;
    public Concept conceptUriPredicate;



    @ManyToMany(
            cascade={CascadeType.ALL }, 
            fetch=FetchType.LAZY
    )   
    @JoinTable(name = "triple_has_annotation", 
            joinColumns={@JoinColumn(name="uri_concept_subject"), @JoinColumn(name="uri_concept_object"), @JoinColumn(name="uri_concept_predicate") },          
            inverseJoinColumns=@JoinColumn(name="annotation_id") )
    public List<Annotation> getAnnotations() {
        return annotations;
    }
    public void setAnnotations(List<Annotation> annotations) {
        this.annotations = annotations;
    }
    @Id 
    @Column(name = "uri_concept_subject", length = 100)
    public Concept getConceptUriSubject() {
        return conceptUriSubject;
    }
    public void setConceptUriSubject(Concept conceptUriSubject) {
        this.conceptUriSubject = conceptUriSubject;
    }
    @Id 
    @Column(name = "uri_concept_object", length = 100)
    public Concept getConceptUriObject() {
        return conceptUriObject;
    }
    public void setConceptUriObject(Concept conceptUriObject) {
        this.conceptUriObject = conceptUriObject;
    }
    @Id 
    @Column(name = "uri_concept_predicate", length = 100)
    public Concept getConceptUriPredicate() {
        return conceptUriPredicate;
    }
    public void setConceptUriPredicate(Concept conceptUriPredicate) {
        this.conceptUriPredicate = conceptUriPredicate;
    }

}
  

Ответ №2:

Я не уверен, что это является причиной получаемого вами сообщения об ошибке, но в вашем сопоставлении есть несколько ошибок:

  1. У каждого из @JoinColumn в вашем inverseJoinColumns атрибуте должен быть указан свой referencedColumnName атрибут.
  2. Значения атрибутов joinColumns и inverseJoinColumns должны быть переключены. joinColumns используется для ссылки на исходный объект. inverseJoinColumns используется для ссылки на целевой объект.
  3. mappedBy Атрибут должен быть annotations , а не annotation
  4. (несвязанный, но, вероятно, неверный) : cascade=CascadeType.ALL вероятно, это не то, что вы хотите для многие-ко-многим. Вы не хотите удалять все аннотации тройки при удалении этой тройки, поскольку на эти аннотации ссылаются другие тройки.

Комментарии:

1. Спасибо за ответ, но я все еще получаю ту же ошибку. Ссылочное имяcolumnname такое же для trhee, будет ли это проблемой?? В любом случае, я проверю CascadeType, спасибо

2. Имя ссылочного столбца должно быть именем столбца в тройной таблице, а не случайным именем (т. Е. Оно используется, чтобы сообщить Hibernate, что столбец uri_concept_subject таблицы triple_has_annotation ссылается на столбец uri_concept_subject тройной таблицы. И я думаю, что нашел проблему: значения атрибутов joinColumns и inverseJoinColumns должны быть переключены.

3. Ссылочный столбец — это имя столбца в таблице аннотаций, то есть annotation_id , потому что я хочу выполнить соединение между Triple и Annotation. uri_concept_subject это имя в базе данных поля conceptUriSubject на Triple.java Это правильно?? Спасибо

Ответ №3:

 @ManyToMany(
        cascade={CascadeType.ALL},
        mappedBy = "annotation",
        fetch=FetchType.LAZY
)   
public List<TripleDBModel> getTriples() {
    return triples;
}
  

mappedBy Должно быть «аннотацииs«.

Редактировать: Взгляните на этот wikibook, особенно на нижний раздел. Это довольно хорошая ссылка для сопоставлений ассоциаций и т.д.