#java #hibernate #jpa #spring-security #spring-data-jpa
#java #переход в спящий режим #jpa #spring-безопасность #spring-data-jpa
Вопрос:
Я пишу простую базу данных инвентаризации, которая содержит таблицы для продуктов, заказов и клиентов. Определение базы данных можно найти здесь:
CREATE TABLE public.customers
(
id integer NOT NULL DEFAULT nextval('customers_id_seq'::regclass),
title character varying(10) COLLATE pg_catalog."default" NOT NULL,
first_name character varying(50) COLLATE pg_catalog."default" NOT NULL,
middle_names character varying(50) COLLATE pg_catalog."default",
last_name character varying(50) COLLATE pg_catalog."default" NOT NULL,
email character varying(50) COLLATE pg_catalog."default" NOT NULL,
phone_number character varying(50) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT customers_pkey PRIMARY KEY (id)
)
CREATE TABLE public.products
(
id integer NOT NULL DEFAULT nextval('products_id_seq'::regclass),
name character varying(100) COLLATE pg_catalog."default" NOT NULL,
sku integer NOT NULL,
inventory_on_hand integer NOT NULL,
reorder_threshold integer NOT NULL,
price numeric(5,2),
inventory_to_be_shipped integer NOT NULL,
CONSTRAINT products_pkey PRIMARY KEY (id)
)
CREATE TABLE public.order_items
(
id integer NOT NULL DEFAULT nextval('order_items_id_seq'::regclass),
product_id integer NOT NULL,
order_id integer NOT NULL,
CONSTRAINT order_items_pkey PRIMARY KEY (id),
CONSTRAINT order_items_order_id_fkey FOREIGN KEY (order_id)
REFERENCES public.orders (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION,
CONSTRAINT order_items_product_id_fkey FOREIGN KEY (product_id)
REFERENCES public.products (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
CREATE TABLE public.orders
(
id integer NOT NULL DEFAULT nextval('orders_id_seq'::regclass),
customer_id integer,
order_date date NOT NULL DEFAULT now(),
arrival_date date,
CONSTRAINT orders_pkey PRIMARY KEY (id),
CONSTRAINT orders_customer_id_fkey FOREIGN KEY (customer_id)
REFERENCES public.customers (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
Я пытаюсь реализовать сервер ресурсов безопасности Spring для выполнения операций CRUD с базой данных. Я реализовал классы сущностей для каждой таблицы в базе данных, но при попытке запустить сервер я получаю
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: edu.finalyearproject.imsresourceserver.models.Order.customers in edu.finalyearproject.imsresourceserver.models.Customer.orders
Мои классы сущности и репозитория можно найти ниже:
Product.java:
@Entity
@Table(name = "products")
@Data
public class Product
{
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String name;
private Integer sku;
private Float price;
private Integer inventory_on_hand;
private Integer reorder_threshold;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinTable(
name = "order_items",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "order_id")
)
private Set<Order> orders = new HashSet<>();
}
Customer.java
@Entity
@Table(name = "customers")
@Data
public class Customer
{
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String title;
private String first_name;
private String middle_names;
private String last_name;
private String email;
private String phone_number;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Order> orders;
}
Order.java
@Entity
@Table(name = "orders")
@Data
public class Order
{
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
@ManyToOne
@JoinColumn(name="customer_id", nullable=false)
private Customer customer;
private Date order_date;
private Date arrival_date;
@ManyToMany(mappedBy = "orders", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Product> products = new HashSet<>();
}
Я знаю, что проблема связана с отношениями между объектами, но я не смог найти решение. Любая помощь будет с благодарностью принята.
Ответ №1:
Попробуйте исправить это:
@Entity
public class Customer
{
// ...
@OneToMany(mappedBy = "orders", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Order> orders;
}
для этого:
@Entity
public class Customer
{
// ...
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Order> orders;
}
Смотрите дополнительное объяснение в документации.
И вы также должны исправить свою Product
— Order
@ManyToMany
ассоциацию. Только одна сторона этой ассоциации должна использовать @JoinTable
, другая сторона должна использовать mappedBy
свойство @ManyToMany
аннотации. Что-то вроде этого:
@Entity
public class Product
{
// ...
@ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.LAZY
)
@JoinTable(
name = "order_items",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "order_id")
)
private Set<Order> orders = new HashSet<>();
}
@Entity
public class Order
{
// ...
@ManyToMany(
mappedBy = "orders",
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.LAZY)
private Set<Product> products = new HashSet<>();
}
Как указано в документации:
Для
@ManyToMany
ассоциацийREMOVE
переход состояния объекта не имеет смысла каскадировать, поскольку он будет распространяться за пределы таблицы ссылок. Поскольку на другую сторону могут ссылаться другие объекты на родительской стороне, автоматическое удаление может закончиться вConstraintViolationException
.
Также, как это объясняется в этом разделе документации:
Если вы забудете
JOIN FETCH
всеEAGER
ассоциации, Hibernate выдаст дополнительный выбор для каждого из них, что, в свою очередь, может привести к N 1 проблемам с запросами.По этой причине вы должны отдавать предпочтение ЛЕНИВЫМ ассоциациям.
Комментарии:
1. Привет, спасибо за комментарий! Я исправил свои классы сущностей, как вы предложили, но я все еще получаю
mappedBy reference an unknown target entity property: edu.finalyearproject.imsresourceserver.models.Order.customer in edu.finalyearproject.imsresourceserver.models.Customer.orders
, что обновил фрагменты кода, чтобы показать изменения2. Похоже, что вы используете
mappedBy = "customers"
, но вы должны использоватьmappedBy = "customer"
.3. Еще раз спасибо за ответ @SternK, я использую mappedBy = «customer», но я все еще получаю то же исключение, мне интересно, может ли мне понадобиться аннотация join для клиента в Order.java ? Когда я включаю
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="customer_id", nullable=false) private Customer customer;
в Order.java Я получаюPropertyReferenceException: No property first found for type Customer!
4. В вашем исключении указано: mappedBy ссылается на неизвестное свойство целевого объекта: edu.finalyearproject.imsresourceserver.models. Заказ.клиенты , которые определенно указывают, что вы используете
mappedBy = "customers"
,edu.finalyearproject.imsresourceserver.models.Customer.orders
пожалуйста, перепроверьте его. Пожалуйста, предоставьте фактическую трассировку стека исключений.5. хорошо, вы были на 100% правы, ваше решение сработало так, как вы заявили, где я ошибся, так это удалил атрибут customer, который соединял столбцы в Order.java , поскольку вы не включили его в свое решение, я ошибочно предположил, что его нужно удалить. Второе исключение, о котором я упомянул в своем следующем комментарии, было отдельной проблемой, вызванной тем, что в моем CustomerRepository был указан неверный метод. Спасибо за всю помощь!