I have written a service method importCategories() which retrieves a list of categories from database and recursively fills in properties and parent categories. The problem I'm experiencing is that new categories are created twice, except when I annotate complete() with @Transactional. Can anyone explain to me why that is? I save the child before adding it to the parent, and afterwards save the parent which has CascadeType.ALL on the child collection.
Model:
@Entity public class Category implements Identifiable<Integer> { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer key; private String name; @ManyToOne private Category parent; @OneToMany(mappedBy="parent", cascade = {CascadeType.ALL}) private List<Category> children = new ArrayList<Category>(); public void add(Category category) { category.setParent(this); children.add(category); } } Service:
@Transactional private void complete(Category category) { // ... (getting category info such as "name" and "parent key" from web service) category.setName(name); category = categoryRepository.saveAndFlush(category); if (category.getParent() == null) { Category parentCategory = new Category(); parentCategory.setKey(parentKey); List<Category> categories = categoryRepository.findByKey(parentKey); if (categories.size() > 0) { parentCategory = categories.get(0); } parentCategory.add(category); parentCategory = categoryRepository.saveAndFlush(parentCategory); if (parentCategory.getParent() == null) { complete(parentCategory); } } } public void importCategories() { List<Category> list = categoryRepository.findAll(); for (Category category : list) { complete(category); } }