I'm developing an ecommerce backend in Spring boot. There is a 1:1 relationship between the two entities Order
and Payment
. At first, I create a Payment
(with order
field null), when the payment is succesful (suppose always in this case), I create the order related to the payment created. The problem is that the Order
entity is created but it isn't connected with the Payment
entity because when I try to print the order in the PaymentService it says that the order is stil null for that payment (even if, in createOrder
method, I did payment.setOrder(o);
as shown below). Moreover, if from the database I try to delete the payment, it tells me that the payment could not be removed because it is connected to the order, but strangely, when I try to print the order of the payment that I have created, the result is null.
OrderService:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@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) {
System.out.println("UserId: " userId);
System.out.println("Payment: " paymentId);
System.out.println("cartId: " cartId);
if(userRepository.existsById(userId)){
System.out.println("Exists");}
User user = userRepository.findById(userId);
if(user==null){
System.out.println("User is null");
}
Payment payment = paymentRepository.findById(paymentId);
System.out.println("Payment: " payment);
Cart c = cartRepository.findById(cartId);
Order o = new Order();
o.setPayment(payment);
o.setCart(c);
o.setBuyer(user);
Order justAdded = orderRepository.save(o);
entityManager.refresh(justAdded);
entityManager.refresh(o);
payment.setOrder(o);
entityManager.refresh(payment);
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();
}
System.out.println("Sto salvando il pagamento: " p);
Order newOrder = new Order();
newOrder.setPayment(p);
Order justAdded=orderRepository.save(newOrder);
entityManager.refresh(justAdded);
p.setOrder(justAdded);
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);
}
}
}
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)
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;
}
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;
@ManyToOne
@JoinColumn(name = "buyer")
private User buyer;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "payment_id")
@JsonIgnore
private Payment payment;
@OneToOne
@JoinColumn(name = "cart_id")
private Cart cart;
}
I have the following method in PaymentService
:
@Transactional(readOnly = true)//
public List<Payment> getAllPayments(){
List<Payment> result = paymentRepository.findAll();
for(Payment p: result){
if(p.getOrder()==null)
System.out.println("Order in payment is null");
}
return paymentRepository.findAll();
}
And when I execute it (after having created a Payment
, an Order
and tried to connect them using the createOrder
method),
Order in payment is null
is printed, so the field order
for that Payment
is still null.
While, the Order
oject is created in the following way in the database:
I've edited createOrder
method, as suggested, in the following way, but the problem persists:
@Transactional(readOnly = false)
public Order createOrder (int paymentId, int userId, int cartId) throws PaymentDoesNotExistException{
User user = userRepository.findById(userId);
Payment payment = paymentRepository.findById(paymentId);
if(payment == null)
{ throw new PaymentDoesNotExistException();
}
System.out.println("Payment: " payment);
Cart c = cartRepository.findById(cartId);
Order o = new Order();
o.setPayment(payment);
o.setCart(c);
o.setBuyer(user);
payment.setOrder(o);
orderRepository.save(o);
return o;
}
CodePudding user response:
I saw couple of unwanted things. No need to call refresh. Just create child objects and save them first and then save the parent. Just a guidance here, make your own custom exceptions and messages.
Payment payment = paymentRepository.findById(paymentId);
if(payment == null)
{ throw Exception("Payment not found");}
System.out.println("Payment: " payment);
Cart c = cartRepository.findById(cartId);
Order o = new Order();
o.setPayment(payment);
o.setCart(c);
o.setBuyer(user);
orderRepository.save(o);