Постоянные аннотации Spring Data Rest - PullRequest
0 голосов
/ 27 сентября 2018

Я изучаю Spring-Data-REST и столкнулся с проблемой, связанной с моими аннотациями.В настоящее время у меня есть следующая схема:

create table user
(
    ID int NOT NULL auto_increment, 
    NAME VARCHAR(60) NOT NULL,
    PASS VARCHAR(20) NOT NULL,
    primary key (ID)
);

create table recipe
(
    ID int NOT NULL auto_increment,
    NAME varchar(60) NOT NULL, 
    USER_ID int NOT NULL,
    primary key (ID),
    FOREIGN KEY (USER_ID) REFERENCES user(ID) ON DELETE CASCADE
);

create table ingredient
(
    ID int not null auto_increment,
    NAME varchar(60) not null,
    primary key(ID)
);

create table ingredientsList 
(
    ID int NOT NULL auto_increment,
    NAME varchar(60) NOT NULL,
    RECIPE_ID int not null,
    INGREDIENT_ID int not null,
    QUANTITY int not null,
    primary key (ID),
    foreign key (RECIPE_ID) REFERENCES recipe(ID) on delete cascade,
    foreign key (INGREDIENT_ID) references ingredient(ID) on delete cascade
);

create table direction
(
    ID int NOT NULL auto_increment,
    NAME varchar(60) NOT NULL,
    RECIPE_ID int not null,
    STEP int not null,
    DESCRIPTION varchar(256),
    primary key (ID),
    foreign key (RECIPE_ID) REFERENCES recipe(ID) on delete cascade
);

У меня есть все таблицы, представленные в моем Spring Data REST API, за исключением одной, которая является таблицей ингредиентов.Вот моя текущая реализация, которая не работает правильно при запуске. \ Mvn clean install:

import java.util.Objects;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

@Entity
public class IngredientsList extends AbstractEntity {

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(nullable=false)
    private Recipe recipe;
    @OneToMany(mappedBy = "ingredientsList", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Ingredient> ingredients;
    @Column(nullable = false)
    private Long quantity;

    public Recipe getRecipe() {
        return recipe;
    }

    public void setRecipe(Recipe recipe){
        this.recipe = recipe;
    }

    public Set<Ingredient> getIngredients() {
        return ingredients;
    }

    public void setIngredients(Set<Ingredient> ingredients){
        this.ingredients = ingredients;
    }

    public Long getQuantity(){
        return quantity;
    }

    public void setQuantity(Long quantity){
        this.quantity = quantity;
    }

    public Long getResourceId() {
        return id;
    }

    // Compares Ingredients
    @Override
    public boolean equals(Object obj) {
        return Objects.equals(id, ((Ingredient) obj).id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

}

Вот мой класс Ingredient:

import javax.persistence.Entity;

@Entity
public class Ingredient extends AbstractEntity {

    public Long getResourceId() {
        return id;
    }
}

Вот мой класс AbstractEntity:

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public class AbstractEntity {
    @Id
    @Column(nullable = false, updatable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    String name;

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

В настоящий момент я сталкиваюсь с ошибкой:

Ошибка создания компонента с именем entityManagerFactory, определенным в ресурсе пути к классу [org / springframework / boot / autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: сбой вызова метода init;вложенное исключение: org.hibernate.AnnotationException: mappedBy ссылается на неизвестное свойство целевого объекта: com.mjf.beerstein.entities.Ingredient.ingredientsList в com.mjf.beerstein.entities.IngredientsList.ingredients

IЯ уверен, что моя проблема - мои аннотации, хотя я не уверен, как их исправить.Часть данных примера для таблицы ингредиентов будет выглядеть следующим образом, где идентификаторы для рецепта и ингредиента связаны между собой и имеют определенное количество:

ID Name     Recipe_ID  Ingredient_ID  Quantity
1  "n/a"    1          1              2
2  "n/a"    1          2              1
3  "n/a"    1          5              1
4  "n/a"    2          1              2

Вот зависимости моего файла pom.xml:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Я нашел ответ здесь:

https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Join_Table

Я полностью покончил с сущностью и хранилищем IngredientsList и вместо этого добавил в свою сущность Recipe.java следующее:

    @OneToMany
    @JoinTable
    (
        name="ingredientslist",
        joinColumns={@JoinColumn(name="recipe_id", referencedColumnName="ID")},
        inverseJoinColumns={@JoinColumn(name="ingredient_id", referencedColumnName="ID", unique=true)}
    )
    private Set<Ingredient> ingredients;

Я также удалил атрибуты ID и Name из таблицы ингредиентов, так как они были ненужными.Это позволяет мне просматривать таблицу со списком ингредиентов и извлекать каждый ингредиент для рецепта через API.Запрашивая конечную точку рецепта, я получаю это:

{
    "_embedded": {
        "recipes": [
            {
                "name": "Coffee Stout",
                "resourceId": 1,
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/api/recipes/1"
                    },
                    "recipe": {
                        "href": "http://localhost:8080/api/recipes/1"
                    },
                    "user": {
                        "href": "http://localhost:8080/api/recipes/1/user"
                    },
                    "ingredients": {
                        "href": "http://localhost:8080/api/recipes/1/ingredients"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/recipes{?page,size,sort}",
            "templated": true
        },
        "profile": {
            "href": "http://localhost:8080/api/profile/recipes"
        }
    },
    "page": {
        "size": 5,
        "totalElements": 1,
        "totalPages": 1,
        "number": 0
    }
}

И, следуя конечной точке к выводу ингредиентов, я получаю это:

{
    "_embedded": {
        "ingredients": [
            {
                "name": "wheat grain",
                "resourceId": 1,
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/api/ingredients/1"
                    },
                    "ingredient": {
                        "href": "http://localhost:8080/api/ingredients/1"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/recipes/1/ingredients"
        }
    }
}

Спасибо всем за помощь в отладке!

0 голосов
/ 27 сентября 2018

Ваша аннотация @OneToMany в классе IngredientsList подразумевает, что в классе Ingredient должно быть поле ingredientsList, которого нет.В вашей схеме у вас есть поле INGREDIENT_ID в вашей таблице ingredientsList, что означает, что IngredientsList может иметь только один Ingredient.

Я думаю, что вы хотели, чтобы IngredientsList имел многоIngredient children, что означает, что таблица ingredient должна иметь поле INGREDIENT_LIST_ID в качестве внешнего ключа к таблице ingredientsList, а класс Ingredients должен иметь поле ingredientsList.Поле INGREDIENT_ID должно быть удалено из таблицы ingredientsList.


Если у IngredientsList должен быть только один Ingredient, тогда измените

@OneToMany(mappedBy = "ingredientsList", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Ingredient> ingredients;

на

@ManyToOne
@JoinColumn("ingredient_id")
private Ingredient ingredient

добавьте cascade и orphanRemoval по мере необходимости.@ManyToOne должен по умолчанию извлекать объединенные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...