Spring Boot: найдены общие ссылки на ошибку коллекции - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь создать небольшое CRUD-приложение Spring Boot с некоторыми базовыми функциями электронной коммерции (например, добавить в корзину и т. Д.).Мои Базовые сущности - это клиенты, сыр, роли и заказы.

У клиентов много-много отношений с объектами Cheese (вымышленный объект, который я продаю).Кроме того, Ордены имеют отношение многие ко многим с объектами Cheese.Когда мой клиент выписывается, я собираюсь передать содержимое корзины (то есть список сыров) в объект Order вместе с идентификатором клиента, общей стоимостью и т. Д. Я хочу, чтобы "Orders" могли регистрироваться самостоятельно, а также предоставить историю заказов для клиента.Создание экземпляра объекта заказа с помощью customer.getCheeses () - это то, что дает мне ошибку общей коллекции.

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

Обработка заказов выполняется в функции completeOrder () в UserController .Все html / thymeleaf, кажется, работают - я могу опубликовать его, если это поможет.

Сыр

package com.example.demo.models;

import javax.persistence.*;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Cheese {

    @NotNull
    @Size(min=2, max=20)
    private String name;


    @NotNull
    @Size(min=2, max=20)
    private String description;

    @NotNull
    @DecimalMax("10000.0") @DecimalMin("0.0")
    private BigDecimal price;

    @Id
    @GeneratedValue
    private int id;


    @ManyToMany(mappedBy = "cheeses")
    private List<Customer> customers = new ArrayList<>();

    @ManyToMany(mappedBy = "cheeses")
    private List<Orders> orders = new ArrayList<>();

    public Cheese() {}

    public Cheese(String name, String description, BigDecimal price) {
        this.name = name;
        this.description = description;
        this.price = price;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<Orders> getOrders() {
        return orders;
    }

    public void setOrders(List<Orders> orders) {
        this.orders = orders;
    }
}

Клиент

package com.example.demo.models;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Customer implements Serializable {

    @NotNull
    @Size(min = 2, max = 25)
    private String name;

    @GeneratedValue
    @Id
    private int accountNumber;

    private BigDecimal accountFunds;

    @NotNull
    @Size(min = 2)
    private String password;

    @NotNull
    @Size(min = 2, max = 25)
    @Email
    private String email;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="user_roles",
            joinColumns={@JoinColumn(name="CUSTOMER_EMAIL", referencedColumnName = "email")},
            inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="id")})
    private List<Role> roles;

    //@ElementCollection

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="cheese_customers",
            joinColumns={@JoinColumn(name="CUSTOMER_ID", referencedColumnName = "accountNumber")},
            inverseJoinColumns={@JoinColumn(name="PRODUCT_ID", referencedColumnName="id")})
    private List<Cheese> cheeses = new ArrayList<>();


    public Customer(String name, String password, String email) {
        this.name = name;
        this.password = password;
        this.email = email;
        this.accountFunds = new BigDecimal(225.00);
    }

    public Customer() {}

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAccountNumber() {
        return accountNumber;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public BigDecimal getAccountFunds() {
        return accountFunds;
    }

    public void setAccountFunds(BigDecimal accountFunds) {
        this.accountFunds = accountFunds;
    }

    public List<Cheese> getCheeses() {
        return cheeses;
    }

    public void setCheeses(List<Cheese> cheeses) {
        this.cheeses = cheeses;
    }
}

Заказы

package com.example.demo.models;

import javax.persistence.*;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Entity
public class Orders {

    @GeneratedValue
    @Id
    private int orderId;

    @ManyToMany(cascade= CascadeType.ALL)
    @JoinTable(name="customer_orders",
            joinColumns={@JoinColumn(name="ORDER_ID", referencedColumnName = "orderId")},
            inverseJoinColumns={@JoinColumn(name="PRODUCT_ID", referencedColumnName="id")})
    private List<Cheese> cheeses = new ArrayList<>();

    private int customerId;

    private BigDecimal totalPrice;

    private Date date;

    public Orders() {}

    public Orders(List<Cheese> cheeses, int customerId, BigDecimal totalPrice) {

        this.cheeses = cheeses;
        this.customerId = customerId;
        this.totalPrice = totalPrice;

        this.date = new Date();
    }

    private String getFormattedDate() {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(this.date);
    }

    public int getOrderId() {
        return orderId;
    }

    public List<Cheese> getCheeses() {
        return cheeses;
    }

    public void setCheeses(List<Cheese> cheeses) {
        this.cheeses = cheeses;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}

UserController

package com.example.demo.controllers;

import com.example.demo.models.Customer;
import com.example.demo.models.Orders;
import com.example.demo.models.data.CheeseDao;
import com.example.demo.models.data.CustomerDao;
import com.example.demo.models.data.OrdersDAO;
import com.example.demo.models.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

@Controller
@RequestMapping("cheese")
public class UserController {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    UserService userService;

    @Autowired
    CheeseDao cheeseDao;

    @Autowired
    OrdersDAO ordersDAO;

    @RequestMapping(value = "login")
    public String loginPage(Model model) {
        model.addAttribute("title", "Login Page");
        model.addAttribute("customer", new Customer());
        return "cheese/login";
    }

    @RequestMapping(value = "account")
    public String accountInfo(Model model) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Customer customer = customerDao.findByEmail(authentication.getName());

        model.addAttribute("name", customer.getName());
        model.addAttribute("funds", customer.getAccountFunds());
        model.addAttribute("customer", customer);
        model.addAttribute("cheeses", customer.getCheeses());
        model.addAttribute("total", userService.getCartTotal(customer));

        return "cheese/account";
    }

    @PostMapping(value = "account")
    public String removeItem(@RequestParam int cheeseId) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Customer customer = customerDao.findByEmail(authentication.getName());

        if (customer.getCheeses().contains(cheeseDao.getCheeseById(cheeseId))) {
            customer.getCheeses().remove(cheeseDao.getCheeseById(cheeseId));
        }

        customerDao.save(customer);

        return "redirect:/cheese/account";

    }

    @RequestMapping(value = "checkout")
    public String orderCheckout(Model model) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Customer customer = customerDao.findByEmail(authentication.getName());

        model.addAttribute("cheeses", customer.getCheeses());
        model.addAttribute("total", userService.getCartTotal(customer));

        return "cheese/checkout";
    }

    @GetMapping("signup")
    public String displaySignUpForm(Model model) {
        model.addAttribute("title", "Sign Up");
        model.addAttribute("customer", new Customer());
        return "cheese/signup";
    }

    @PostMapping(value = "signup")
    public String processSignUp(Model model, @ModelAttribute Customer customer, Errors errors) {

        if (errors.hasErrors()) {
            return "cheese/signup";
        }

        userService.createUser(customer);
        return "cheese/success";
    }

    @GetMapping("ordersuccess")
    public String showForm() {
        return "cheese/ordersuccess";
    }


    @PostMapping("checkout")
    public String completeOrder() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Customer customer = customerDao.findByEmail(authentication.getName());

        double accountFunds = customer.getAccountFunds().doubleValue();
        double cartTotal = userService.getCartTotal(customer).doubleValue();

        if (accountFunds >= cartTotal) {
            accountFunds = accountFunds - cartTotal;

        customer.setAccountFunds(new BigDecimal(accountFunds));

        Orders order = new Orders(customer.getCheeses(), customer.getAccountNumber(), new BigDecimal(cartTotal));
        customer.getCheeses().clear();

        customerDao.save(customer);
        ordersDAO.save(order);

        return "redirect:/cheese/ordersuccess";
        }
        return "redirect:cheese/checkout";
    }

    @GetMapping("orders")
    public String viewOrderHistory(Model model) {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Customer customer = customerDao.findByEmail(authentication.getName());

        List<Orders> orders = ordersDAO.findOrdersByCustomerId(customer.getAccountNumber());
        model.addAttribute("orders", orders);

        return "cheese/orders";
    }

}

1 Ответ

0 голосов
/ 07 июня 2018

Итак, что вы пытаетесь сделать, это собрать и заполнить коллекцию сыра, когда вы получаете клиента?Обычно, чтобы сделать это, вы должны установить для отложенной загрузки значение false, иначе сеанс закрывается, прежде чем вы сможете получить коллекцию.

Чтобы иметь возможность загрузить клиента с его коллекцией сыра, вы должны получить запрос Hibernate и использовать команду "join fetch".Примерно так.

sessionFactory.getCurrentSession().createQuery("from Customer C join fetch C.cheeses").list();

Это заставит запрос извлечь коллекцию сыра до закрытия сессии.Кроме того, еще одна вещь, обычно я бы использовал набор, чтобы избежать дубликатов в коллекции.Надеюсь, это поможет.

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