Introduction to antecedents
Java beans are used as containers to hold data for daily work. I found a problem in my work:
The business entity is to split an order. The order is divided into main part and detail part. There can be multiple details. After splitting, the order is reorganized to calculate the total amount. The specific business is more complex than this. Here is a brief description of the problem.
Business simulation
Class order, class orderhead and orderdetail are defined as Java objects here, and simple properties are defined as follows:
@Setter @Getter class Order { private OrderHead orderHead; private List<OrderDetail> orderDetails; } @Setter @Getter @AllArgsConstructor @NoArgsConstructor class OrderHead { private String orderId; private String productName; private String orderMoney; } @Setter @Getter @AllArgsConstructor @NoArgsConstructor class OrderDetail { private String detailId; private String detailName; private String detailMoney; }
Because there are many splitting methods involved in specific business, here the total amount of order splitting and recalculation is written in two parts separately. Here, the simulation amount greater than 20 is placed in one order, and the others are placed in another order. Specific method code:
private void resetMoney(List<Order> result) { for (Order order : result) { BigDecimal money = new BigDecimal(0); for (OrderDetail orderDetail : order.getOrderDetails()) { money = money.add(new BigDecimal(Double.valueOf(orderDetail.getDetailMoney()))); } order.getOrderHead().setOrderMoney(String.valueOf(money)); } } private void split(Order order, List<Order> result) { List<OrderDetail> orderDetails = order.getOrderDetails(); Order order1 = new Order(); Order order2 = new Order(); List<OrderDetail> orderDetails1 = new ArrayList<>(); List<OrderDetail> orderDetails2 = new ArrayList<>(); for (OrderDetail orderDetail : orderDetails) { if (Double.valueOf(orderDetail.getDetailMoney()) >= 20) { orderDetails1.add(orderDetail); } else { orderDetails2.add(orderDetail); } } order1.setOrderDetails(orderDetails1); order2.setOrderDetails(orderDetails2); order1.setOrderHead(order.getOrderHead()); order2.setOrderHead(order.getOrderHead()); result.add(order1); result.add(order2); }
There is no problem in this view. It is to split the order details. The main part of the order is placed in two orders, but there is a problem in the specific test. The test code is as follows:
private static JavaBeanRelation relation = new JavaBeanRelation(); // It is required to split the details in order a into one order if it is greater than 20, and recalculate the total amount of head to get the last two orders public static void main(String[] args) { Order order = new Order(); OrderDetail detail1 = new OrderDetail("d1", "dname1", "24"); OrderDetail detail2 = new OrderDetail("d2", "dname2", "25"); OrderDetail detail3 = new OrderDetail("d3", "dname3", "15"); OrderDetail detail4 = new OrderDetail("d4", "dname4", "16"); OrderHead orderHead = new OrderHead("b1", "bname1", "80"); order.setOrderHead(orderHead); List<OrderDetail> orderDetails = new ArrayList<>(); orderDetails.add(detail1); orderDetails.add(detail2); orderDetails.add(detail3); orderDetails.add(detail4); order.setOrderDetails(orderDetails); List<Order> result = new ArrayList<>(); relation.split(order, result); relation.resetMoney(result); //Output the final result JsonUtils as the serialization tool class System.out.println(JsonUtils.getInstance().toJsonString(result)); }
Console output:
[ { "orderDetails": [ { "detailId": "d1", "detailMoney": "24", "detailName": "dname1" }, { "detailId": "d2", "detailMoney": "25", "detailName": "dname2" } ], "orderHead": { "orderId": "b1", "orderMoney": "31", "productName": "bname1" } }, { "orderDetails": [ { "detailId": "d3", "detailMoney": "15", "detailName": "dname3" }, { "detailId": "d4", "detailMoney": "16", "detailName": "dname4" } ], "orderHead": { "orderId": "b1", "orderMoney": "31", "productName": "bname1" } } ]
There is a problem at this time. The last one of the order body is right, 15 + 16 = 31, but how does the first one change? In other words, two orders refer to the same object. When one of them changes, the other also changes. Here, you can copy and recalculate the OrderHead during sorting, or you can directly use two objects during splitting. I use Spring's BeanUtils.copyProperties(Object source, Object target) throws BeansException method. The specific split method is modified as follows:
private void split(Order order, List<Order> result) { List<OrderDetail> orderDetails = order.getOrderDetails(); Order order1 = new Order(); Order order2 = new Order(); List<OrderDetail> orderDetails1 = new ArrayList<>(); List<OrderDetail> orderDetails2 = new ArrayList<>(); for (OrderDetail orderDetail : orderDetails) { if (Double.valueOf(orderDetail.getDetailMoney()) >= 20) { orderDetails1.add(orderDetail); } else { orderDetails2.add(orderDetail); } } order1.setOrderDetails(orderDetails1); order2.setOrderDetails(orderDetails2); order1.setOrderHead(order.getOrderHead()); OrderHead orderHeadCopy = new OrderHead(); BeanUtils.copyProperties(order.getOrderHead(),orderHeadCopy); order2.setOrderHead(orderHeadCopy); result.add(order1); result.add(order2); }
After the modification is completed, the result is correct. You can use debug to view the specific details. After splitting, the order can see that the referenced objects are the same. This article will not elaborate. The next article will explain why the clone method is not applicable.