Issue
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
:
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:
Solution
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;
}
Answered By - Giovanna
Answer Checked By - Marilyn (JavaFixing Volunteer)