org.hibernate.HibernateException:找到具有给定标识符的多行:40,对于 class:com.ptoject.demo.entities.User

org.hibernate.HibernateException: More than one row with the given identifier was found: 40, for class: com.ptoject.demo.entities.User

我正在 Spring 启动开发电子商务后端。每次我为同一个 User 创建两个以上的 Order 时,我都会收到以下错误:org.hibernate.HibernateException: More than one row with the given identifier was found: 40, for class: com.ptoject.demo.entities.User。 要创建一个 Order,我首先创建一个 Payment,然后创建由 Payment 生成的 Order,因此问题可能出在创建 [=27] =] 也是。

Order实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity

@Table(name = "order", schema = "purchase")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "order_time")
    private Date orderTime;

    @OneToMany(mappedBy = "order", cascade = CascadeType.MERGE)
    private List<ProductInOrder> productsInOrder;

    @ManyToOne
    @JoinColumn(name = "buyer")
    private User buyer;

    @OneToOne
    @JoinColumn(name = "payment_id")
    @JsonIgnore
    private Payment payment;

    @OneToOne
    @JoinColumn(name = "cart_id")
    private Cart cart;
}

User实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity
@Table(name="user", schema = "purchase")

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;


    @Basic
    @Column(name = "code", nullable = true, length = 70)
    private String code;

    @Basic
    @Column(name = "first_name", nullable = true, length = 50)
    private String firstName;

    @Basic
    @Column(name = "last_name", nullable = true, length = 50)
    private String lastName;

    @Basic
    @Column(name = "telephone", nullable = true, length = 20)
    private String telephone;

    @Basic
    @Column(name = "email", nullable = true, length = 90)
    private String email;

    @Basic
    @Column(name = "password", nullable = true, length = 90)
    private String password;

    @Basic
    @Column(name = "address", nullable = true, length = 150)
    private String address;


    @OneToMany(mappedBy = "buyer", cascade = CascadeType.MERGE)
    @JsonIgnore
    private List<Order> orders;

    @OneToMany(mappedBy = "user", cascade = CascadeType.MERGE)
    @JsonIgnore
    private List<QuestionForUser> questionsForUser;

    @OneToOne(mappedBy = "buyer")
    @JsonIgnore
    private Cart cart;

    @OneToMany(mappedBy = "user", cascade = CascadeType.MERGE)
    @JsonIgnore
    private List<Answer> answer;

}

Payment实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity
@Table(name = "payment", schema = "purchase")
public class Payment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @Column(name = "owner_name", nullable = true, length = 70)
    private String ownerName;

    @Basic
    @Column(name = "owner_last_name", nullable = true, length = 70)
    private String ownerLastName;

    @Basic
    @Column(name = "card_number", nullable = true, length = 16)
    //il numero di una carta PayPal è di 16 cifre
    private String cardNumber;

    @Basic
    @Temporal(TemporalType.DATE)

    @Column(name = "expiration", nullable = true)
    private Date expiration;

    @Basic
    @Column(name = "cvv", nullable = true, length = 3)
    private String cvv;

    @Basic
    @Column(name = "total", nullable = true)
    private float total;

    @OneToOne(mappedBy = "payment")
    private Order order;
}

OrderService:

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ProductInOrderRepository productInOrderRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private CartRepository cartRepository;

    @Autowired
    private PaymentRepository paymentRepository;

    @Autowired
    private EntityManager entityManager;

@Transactional(readOnly = false)
    public Order createOrder (int paymentId, int userId, int cartId) {

        User user = userRepository.findById(userId);
        Payment payment = paymentRepository.findById(paymentId);
        Cart c = cartRepository.findById(cartId);
        List<ProductInOrder> productsInOrder=new LinkedList<>();
        List<ProductInCart> productsInCart=c.getProductsInCart();
        Order o = new Order();
        o.setPayment(payment);
        o.setCart(c);
        o.setBuyer(user);
        for(ProductInCart productInCart: productsInCart){
            ProductInOrder productInOrder = new ProductInOrder();
            productInOrder.setProduct(productInCart.getProduct());
            productInOrder.setOrder(o);
            productInOrder.setQuantity(productInCart.getQuantity());
            productInOrderRepository.save(productInOrder);
            productsInOrder.add(productInOrder);
        }
        o.setProductsInOrder(productsInOrder);
        payment.setOrder(o);
        Order justAdded = orderRepository.save(o);
        entityManager.refresh(justAdded);
        entityManager.refresh(o);
        return justAdded;

    }

OrderController:

@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/create")
    @ResponseStatus(code = HttpStatus.OK)
    public ResponseEntity<Order> createOrder (@RequestParam(required = false) int paymentId,
                                                    @RequestParam(required = false) int buyerId,
                                                    @RequestParam(required = false) int cartId){

            return new ResponseEntity<>(orderService.createOrder(paymentId, buyerId, cartId), HttpStatus.OK);

    }

PaymentService:

@Service
public class PaymentService {

    @Autowired
    private PaymentRepository paymentRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private EntityManager entityManager;

    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public Payment addPayment(Payment p) throws PaymentAlreadyExistsException, IncorrectCardNumberException, IncorrectCvvException{//
        if(paymentRepository.existsByCardNumber(p.getCardNumber())){
            throw new PaymentAlreadyExistsException();
        }
       
        if(p.getCardNumber().length()!=16){
            throw new IncorrectCardNumberException();
        }
        if(p.getCvv().length()!=3)
        {
            throw new IncorrectCvvException();
        }
        return paymentRepository.save(p);
    }

PaymentController:

@RestController
@RequestMapping("/payments")
public class PaymentController {
    @Autowired
    private PaymentService paymentService;

    @PostMapping("/createPayment")//funziona
    public ResponseEntity<Payment> create(@RequestBody @Valid Payment payment){
        System.out.print("Sono in paymentController.");
        try {
            Payment added=paymentService.addPayment(payment);
            return new ResponseEntity<>(added, HttpStatus.OK);
        } catch (PaymentAlreadyExistsException e) {
            return new ResponseEntity(new ResponseMessage("Payment already exists!"), HttpStatus.BAD_REQUEST);
        } catch (IncorrectCardNumberException e) {
            return new ResponseEntity(new ResponseMessage("Incorrect card number!"), HttpStatus.BAD_REQUEST);
        } catch (IncorrectCvvException e) {
            return new ResponseEntity(new ResponseMessage("Incorrect CVV"), HttpStatus.BAD_REQUEST);
        }
}

异常堆栈跟踪:

org.hibernate.HibernateException: More than one row with the given identifier was found: 44, for class: com.ptoject.demo.entities.User at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.extractEntityResult(AbstractLoadPlanBasedEntityLoader.java:348) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:292) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4521) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4511) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:571) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:539) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:327) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1226) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1215) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl.access00(SessionImpl.java:201) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2830) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.lambda$load(SessionImpl.java:2807) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.perform(SessionImpl.java:2763) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2807) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3395) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3362) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final] at jdk.internal.reflect.GeneratedMethodAccessor116.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362) ~[spring-orm-5.3.14.jar:5.3.14] at jdk.proxy2/jdk.proxy2.$Proxy108.find(Unknown Source) ~[na:na] at jdk.internal.reflect.GeneratedMethodAccessor116.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) ~[spring-orm-5.3.14.jar:5.3.14] at jdk.proxy2/jdk.proxy2.$Proxy108.find(Unknown Source) ~[na:na] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById(SimpleJpaRepository.java:313) ~[spring-data-jpa-2.6.0.jar:2.6.0] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new[=41=](RepositoryMethodInvoker.java:289) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:529) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:638) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:163) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.6.0.jar:2.6.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174) ~[spring-data-jpa-2.6.0.jar:2.6.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.14.jar:5.3.14] at jdk.proxy2/jdk.proxy2.$Proxy120.findById(Unknown Source) ~[na:na] at com.ptoject.demo.services.CartService.clearCart(CartService.java:115) ~[classes/:na] at com.ptoject.demo.services.CartService$$FastClassBySpringCGLIB$0368ec.invoke() ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.14.jar:5.3.14] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.14.jar:5.3.14] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.14.jar:5.3.14] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-5.3.14.jar:5.3.14] at com.ptoject.demo.services.CartService$$EnhancerBySpringCGLIB$$ea3d0786.clearCart() ~[classes/:na] at com.ptoject.demo.controller.CartController.clearCart(CartController.java:69) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.14.jar:5.3.14] at org.springframework.web.servlet.FrameworkServlet.doDelete(FrameworkServlet.java:931) ~[spring-webmvc-5.3.14.jar:5.3.14] at javax.servlet.http.HttpServlet.service(HttpServlet.java:671) ~[javaee-web-api-8.0.1.jar:na] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.14.jar:5.3.14] at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) ~[javaee-web-api-8.0.1.jar:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.14.jar:5.3.14] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.14.jar:5.3.14] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.14.jar:5.3.14] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.14.jar:5.3.14] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.14.jar:5.3.14] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.56.jar:9.0.56] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

ProductController.addProductToCart:

 @PostMapping("/addProduct")
    @ResponseStatus(code = HttpStatus.OK)
    public ResponseEntity<Product> addProductToCart(@RequestParam(required = false) int productId,
                                                    @RequestParam(required = false) int userId,
                                                    @RequestParam(required = false) int quantity){
        try {
            return new ResponseEntity<>(productService.addToCart(productId, userId, quantity), HttpStatus.OK);
        } catch (ProductUnavailableException e) {
            return new ResponseEntity(new ResponseMessage("The quantity of product: "+e.getProduct().getName()+" is unavailable!"), HttpStatus.BAD_REQUEST);
        }
    }

ProductService.addToCart:

 @Transactional(readOnly = false, rollbackForClassName = {ProductUnavailableException})
public Product addToCart (int productId, int userId, int quantity) throws ProductUnavailableException {

    User user = userRepository.findById(userId);

    Product product = productRepository.findById(productId);
    Cart c = user.getCart();
    List<ProductInCart> pc = c.getProductsInCart();
    ProductInCart p = new ProductInCart();
    p.setProduct(product);
    p.setCart(c);
    p.setQuantity(quantity);
    ProductInCart justAdded = productInCartRepository.save(p);
    Product pr = justAdded.getProduct();
    int newQuantity = pr.getQuantity() - p.getQuantity();
    if (newQuantity < 0) {
        p.setCart(null);
        productInCartRepository.delete(p);
        throw new ProductUnavailableException(pr);
    }
    product.setQuantity(newQuantity);

    float newTotal=c.getTotal()+pr.getPrice();
    c.setTotal(newTotal);

    return pr;

}

Table Cart:

Cart实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity
@Table(name = "cart", schema = "purchase")
public class Cart {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @Column(name = "total", nullable = true)
    private float total;


    @OneToMany(mappedBy = "cart", cascade = CascadeType.MERGE)
    private List<ProductInCart> productsInCart;


    @OneToOne
    @JoinColumn(name = "user_id")
    private User buyer;

    @OneToOne(mappedBy = "cart")
    @JsonIgnore
    private Order order;

}

User table:

User user = userRepository.findById(userId);

当您的 JPA 方法需要一个结果时,在这种情况下您希望 return 是一个 User 并且有更多的记录要 returned Hibernate 将抛出一个异常,更具体地说是您收到的异常。

解决方案

如果您定义的某些自定义 JPA 方法发生此错误,则应在存储库中将此方法定义为不是 return 单个结果,而是结果列表(如果这是商业上可接受的)。因此,在某些方法中,您应该将定义修改为 return List<User> 而不是 return User 。在这种情况下,当要 returned 多条记录时,Hibernate 将不会抛出此异常。

但在您的情况下,由于它是 Spring 和 findById(userId) 提供的默认方法,并且考虑到它是按主键搜索的,因此上述方法不应是解决方案。您的数据库模式应该是错误的,并且 table.

中的记录也是如此

尝试在数据库中手动更正您的 table User 以将 id 列设为 primary key 并尝试删除相同 [=17] 的多条记录=] 存在。当您清理并更正数据库中的 table 时,应该不会再出现此问题。

在您的代码中,我看不出有任何理由使用 entityManager.refresh。这会产生一些问题。此外,Transactional 不适用于您在代码中抛出的已检查异常。检查以下代码并应用它。清理数据库中的记录,然后使用此代码重试以查看问题是否已消除。

@Transactional(readOnly = false, rollbackForClassName = {ProductUnavailableException})
    public Product addToCart (int productId, int userId, int quantity) throws ProductUnavailableException {
        
        User user = userRepository.findById(userId);
       
        Product product = productRepository.findById(productId);
        Cart c = user.getCart();
        List<ProductInCart> pc = c.getProductsInCart();
        ProductInCart p = new ProductInCart();
        p.setProduct(product);
        p.setCart(c);
        p.setQuantity(quantity);
        ProductInCart justAdded = productInCartRepository.save(p);
        int newQuantity = product.getQuantity() - p.getQuantity();
        if (newQuantity < 0) {
            p.setCart(null);
            productInCartRepository.delete(p);
            throw new ProductUnavailableException(pr);
        }
        product.setQuantity(newQuantity);

        float newTotal=c.getTotal()+product.getPrice();
        c.setTotal(newTotal);

        return product;

    }

我解决了我的问题,我将 post 对我有用的解决方案,以防万一遇到同样问题的人正在寻找解决方案。我在 CartUser 之间有一个 1:1 关系,在 UserOrder 之间有一个 1:n 关系,在 UserOrder 之间有一个 1:1 关系CartOrder。可能,这在关系之间创建了类似循环的东西,所以我通过删除 CartOrder 之间的关系解决了我的问题,并通过以下方式编辑 OrderService.createOrder(paymentId, userId, cartId)

@Transactional(readOnly = false)
    public Order createOrder(int userId, int paymentId) {
        User user = userRepository.findById(userId);
        Payment payment=paymentRepository.findById(paymentId);

        Order o = new Order();
        o.setBuyer(user);
        o.setTotal(payment.getTotal());
        o.setPayment(payment);
        List<ProductInOrder> po=new LinkedList<>();
        List<ProductInCart> pc=user.getCart().getProductsInCart();
        for(ProductInCart productInCart: pc){
            ProductInOrder productInOrder=new ProductInOrder();
            productInOrder.setProduct(productInCart.getProduct());
            productInOrder.setQuantity(productInCart.getQuantity());
            productInOrder.setOrder(o);
            productInOrderRepository.save(productInOrder);
            po.add(productInOrder);
        }

        o.setProductsInOrder(po);


        List<Order> ordersForUser = user.getOrders();
        ordersForUser.add(o);
        user.setOrders(ordersForUser);
        payment.setOrder(o);

        Order justAdded = orderRepository.save(o);
        entityManager.refresh(justAdded);


        entityManager.refresh(o);
        entityManager.refresh(user);
        return justAdded;
}

OrderController.createOrder:

@PostMapping("/create")
    @ResponseStatus(code = HttpStatus.OK)
    public ResponseEntity<Order> createOrder (@RequestParam(required = false) int buyerId,
                                                    @RequestParam(required = false) int paymentId){

            return new ResponseEntity<>(orderService.createOrder(buyerId, paymentId), HttpStatus.OK);

    }

订单实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity

@Table(name = "order", schema = "purchase")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "order_time")
    private Date orderTime;


    @OneToMany(mappedBy = "order", cascade = CascadeType.MERGE)
    private List<ProductInOrder> productsInOrder;


    @ManyToOne
    @JoinColumn(name = "buyer")
    private User buyer;

    @OneToOne
    @JoinColumn(name = "payment_id")
    @JsonIgnore
    private Payment payment;

    @Basic
    @Column(name = "total", nullable = true)
    private float total;
}

购物车实体:

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Entity
@Table(name = "cart", schema = "purchase")
public class Cart {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private int id;

    @Basic
    @Column(name = "total", nullable = true)
    private float total;


    @OneToMany(mappedBy = "cart", cascade = CascadeType.MERGE)
    private List<ProductInCart> productsInCart;


    @OneToOne
    @JoinColumn(name = "user_id")
    private User buyer;

}