Home > OS >  org.hibernate.HibernateException: More than one row with the given identifier was found: 40, for cla
org.hibernate.HibernateException: More than one row with the given identifier was found: 40, for cla

Time:02-13

I'm developing an e-commerce backend in Spring boot. Every time I create more than two Order for the same User, I got the following error: org.hibernate.HibernateException: More than one row with the given identifier was found: 40, for class: com.ptoject.demo.entities.User. To create an Order, I firstly create a Payment and then I create the Order generated by the Payment, so the problem could be in the creation of the Payment too.

Order entity:

@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 entity:

@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 entity:

@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);
        }
}

Exception stack trace:

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.access$2100(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$1(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$0(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$1.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$$280368ec.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$1.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:

enter image description here

Cart entity:

@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:

enter image description here

CodePudding user response:

User user = userRepository.findById(userId);

When your JPA method expects a single result, in this case you expect the return to be a User and there are more records to be returned Hibernate will throw an exception, more specifically the one you have received.

Solution

If this error occurs to some custom JPA method you have defined then this method should be defined in repository to not return a single result but a list of results if this is business wise accepted. So in some method instead of return User you should have modified the definition to return List<User> . In this case when multiple records are to be returned Hibernate will not throw this exception.

But in your case since it is the default method provided by Spring the findById(userId) and considering that it searches by primary key, the above should not be the solution. Your database schema should be wrong and also the records in this table.

Try to manually correct your table User in Database to have the column id as primary key and also try to delete multiple records of the same id that exist. When you clean and correct your table in database, this issue should not appear any more.

In your code I don't see any reason to use entityManager.refresh. This can create some issues. Also the Transactional will not work with a checked exception you throw in your code. Check the following code and apply it. Clean the records in DB and try again with this code to see if issue is eliminated.

@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;

    }

CodePudding user response:

I resoved my problem, I'll post the solution that worked for me just in case somebody, with the same problem, is searching for the solution. I had a 1:1 relationship between Cart and User, a 1:n relationship between User and Order, a 1:1 relationship between Cart and Order. Probably, this created something like a loop between the relationships, so I solved my problem by removing the relatiolnship between Cart and Order an by editing the OrderService.createOrder(paymentId, userId, cartId) in the following way:

@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);

    }

Order entity:

@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;
}

Cart entity:

@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;

}
  • Related