Hibernate MappingException: внешний ключ должен иметь то же количество столбцов, что и указанный первичный ключ - PullRequest
0 голосов
/ 08 июля 2019

У меня есть этот объект, называемый FatRabbitCarrot:

@Entity
public class FatRabbitCarrot {
    private Long id;
    private FatRabbit fatRabbit;
    private Carrot carrot;

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

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

@ManyToOne
@JoinColumn(name = "fatRabbit_id", foreignKey = @ForeignKey(name = "FK_FatRabbitCarrot_fatRabbit"))
public FatRabbit getFatRabbit() {
    return fatRabbit;
}

public void setFatRabbit(FatRabbit fatRabbit) {
    this.fatRabbit = fatRabbit;
}

@ManyToOne
@JoinColumn(name = "carrot_id", foreignKey = @ForeignKey(name = "FK_FatRabbitCarrot_carrot"))
public Carrot getCarrot() {
    return carrot;
}

public void setCarrot(Carrot carrot) {
    this.carrot = carrot;
}
}

И это работает.Теперь в вышеприведенном классе заменены имена полей, но структура такая же, как и в нашем репозитории.

Затем я попытался добавить новую сущность, которая имеет внешний ключ к классу выше.Давайте назовем этот класс NutToffee.FatRabbitCarrot имеет отношение OneToMany к этому новому объекту, в то время как сам объект должен иметь отношение ManyToOne:

@Entity
public class NutToffee {

private Long id;
private String text;
private FatRabbitCarrot fatRabbitCarrot;

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

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

@Basic
@Column(name = "text")
public String getText() {
    return text;
}

public void setText(String text) {
    this.text = text;
}

@ManyToOne
@JoinColumn(name="fatRabbitCarrot_id", foreignKey = @ForeignKey(name = "FK_NutToffee_fatRabbitCarrot"))
public FatRabbitCarrot getFatRabbitCarrot() {
    return fatRabbitCarrot;
}

public void setFatRabbitCarrot(FatRabbitCarrot fatRabbitCarrot) {
    this.fatRabbitCarrot = fatRabbitCarrot;
}
}

Теперь мне кажется, что это допустимый класс.Но это не похоже на это.Мы используем Java 8, Hibernate JPA 2.1, Java EE 7 и Gradle для создания артефакта, который мы хотим развернуть.Мы пытаемся развернуть его на сервере приложений Wildfly 10, но получаем следующую ошибку:

[2019-07-08 03:53:45,441] Artifact Gradle : com.solveralynx.wildrunner : fatties.war: java.lang.Exception: {"WFLYCTL0080: Failed services" => {"jboss.persistenceunit.\"fatties.war#FatUnit\"" => "org.jboss.msc.service.StartException in service jboss.persistenceunit.\"fatties.war#FatUnit\": org.hibernate.MappingException: Foreign key (FK_NutToffee_fatRabbitCarrot:NutToffee [fatRabbitCarrot_id])) must have same number of columns as the referenced primary key (FatRabbitCarrot [fatRabbit_id,carrot_id])
Caused by: org.hibernate.MappingException: Foreign key (FK_NutToffee_fatRabbitCarrot:NutToffee [fatRabbitCarrot_id])) must have same number of columns as the referenced primary key (FatRabbitCarrot [fatRabbit_id,carrot_id])"},"WFLYCTL0412: Required services that are not installed:" => ["jboss.persistenceunit.\"fatties.war#FatUnit\""],"WFLYCTL0180: Services with missing/unavailable dependencies" => undefined}

Насколько я понимаю, Hibernate нашел составной первичный ключ для FatRabbitCarrot?Хотя мы никогда не определяли один?Кажется, что он использует поддельный первичный ключ, где он использует оба внешних ключа от объекта FatRabbitCarrot.

Что касается моего тестирования.Я уверен, что это проблема Hibernate.Независимо от состояния базы данных, я всегда получаю эту ошибку.Я тестировал различные параметры на геттерах, которые связывают эти объекты, но безуспешно.Если я удаляю как новые подключения OneToMany, так и ManyToOne, артефакт развертывается.

Кто-нибудь знает, почему Hibernate делает это?

1 Ответ

0 голосов
/ 08 июля 2019

Вы используете @JoinColumn аннотацию неправильно.

@Entity
public class FatRabbitCarrot {

    @Id
    @GeneratedValue
    private Long id;

    @OnToMany
    private List<NutToffee> toffies;

}

@Entity
public class NutToffee {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "fatRabbitCarrot_id")
    private FatRabbitCarrot fatRabbitCarrot;

}

Это означает, что вы будете иметь связь между FatRabbitCarrot и NutToffee, используя таблицу соединения.И у вас будет дополнительный столбец fatRabbitCarrot_id в таблице NutToffee.

Вам необходимо использовать mappedBy

    @Entity
    public class FatRabbitCarrot {

        @Id
        @GeneratedValue
        private Long id;

        @OnToMany(mappedBy = "fatRabbitCarrot")
        private List<NutToffee> toffies;

    }

    @Entity
    public class NutToffee {

        @Id
        @GeneratedValue
        private Long id;

        @ManyToOne
        @JoinColumn(name = "fatRabbitCarrot_id")
        private FatRabbitCarrot fatRabbitCarrot;

    }

, если вам не нужна ассоциация @ManyToOneВы можете использовать @JoinColumn с @OneToMany без mappedBy

    @Entity
    public class FatRabbitCarrot {

        @Id
        @GeneratedValue
        private Long id;

        @OnToMany
        @JoinColumn(name = "fatRabbitCarrot_id")
        private List<NutToffee> toffies;

    }

    @Entity
    public class NutToffee {

        @Id
        @GeneratedValue
        private Long id;


    }

https://stackoverflow.com/a/37542849/3405171

...