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 对我有用的解决方案,以防万一遇到同样问题的人正在寻找解决方案。我在 Cart
和 User
之间有一个 1:1 关系,在 User
和 Order
之间有一个 1:n 关系,在 User
和 Order
之间有一个 1:1 关系Cart
和 Order
。可能,这在关系之间创建了类似循环的东西,所以我通过删除 Cart
和 Order
之间的关系解决了我的问题,并通过以下方式编辑 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;
}
我正在 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 对我有用的解决方案,以防万一遇到同样问题的人正在寻找解决方案。我在 Cart
和 User
之间有一个 1:1 关系,在 User
和 Order
之间有一个 1:n 关系,在 User
和 Order
之间有一个 1:1 关系Cart
和 Order
。可能,这在关系之间创建了类似循环的东西,所以我通过删除 Cart
和 Order
之间的关系解决了我的问题,并通过以下方式编辑 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;
}