I have a customer json like below
{
"id": "id",
"name": "full name",
"products": [{
"id": "pid1",
"productName": "productName",
"xBenefits": [{
"id": "p1-xbid1",
"name": "benefit name"
},{
"id": "p1-xbid2",
"name": "benefit name"
}],
"yBenefits": [{
"id": "p1-ybid1",
"name": "benefit name"
},{
"id": "p1-ybid2",
"name": "benefit name"
}],
"zBenefits": [{
"id": "p1-zbid1",
"name": "benefit name"
},{
"id": "p1-zbid2",
"name": "benefit name"
}]
},{
"id": "pid2",
"productName": "productName",
"xBenefits": [{
"id": "p2-xbid1",
"name": "benefit name"
},{
"id": "p2-xbid2",
"name": "benefit name"
}],
"yBenefits": [{
"id": "p2-ybid1",
"name": "benefit name"
},{
"id": "p2-ybid2",
"name": "benefit name"
}],
"zBenefits": [{
"id": "p2-zbid1",
"name": "benefit name"
},{
"id": "p2-zbid2",
"name": "benefit name"
}]
}]
}
The corresponding entity classes like below
public class Customer {
String id;
String name;
List<Product> products;
}
public class Product {
String id;
String productName;
List<XBenefit> xBenefits;
List<YBenefit> yBenefits;
List<ZBenefit> zBenefits;
}
public class XBenefit {
String id;
String name;
}
public class YBenefit {
String id;
String name;
}
public class ZBenefit {
String id;
String name;
}
We are using mybatis xml mapper files to insert the records into the tables. Below is some sample service code which does the inserts
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private ProductService productService;
@Autowired
private CustomerMapper customerMapper;
@Override
@Transactional
public void save(Customer customer) {
customerMapper.save(customer);
productService.save(customer.getProducts());
}
}
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Autowired
private XBenefitService xBenefitService;
@Autowired
private YBenefitService yBenefitService;
@Autowired
private ZBenefitService ZBenefitService;
@Override
@Transactional
public void save(List<Product> products) {
for (Product product: products) {
productMapper.save(product)
xBenefitService.save(product.getXBenefits());
yBenefitService.save(product.getYBenefits());
zBenefitService.save(product.getZBenefits());
}
}
}
@Service
public class XBenefitServiceImpl implements XBenefitService {
@Autowired
private XBenefitMapper xBenefitMapper;
@Override
@Transactional
public void save(List<XBenefit> xBenefits) {
xBenefits.forEach(xBenefit -> {
xBenefitMapper.save(xBenefit);
});
}
}
So far everything works good. If a row fails to insert, all the rows inserted thus far are are also rolled back. We have integration tests written for this.
However I think there is a room for improvement here. Once a Product is inserted, I think I can safely insert the corresponding benefits simultaneously. However I am not sure of how to do this using spring @Async and also in the same transaction so that if a benefit fails to insert the entire transaction rolls back.
I did some research on google and gemini AI results are not consistent across searches on my desktop and mobile.
I want the main method to wait until all the products and associated benefits are inserted successfully and then complete. Something like rxjx's forkjoin.
Can anyone please shed some light here, point me to a step by step guide if one exists somewhere over the web? Thanks much.