Spring Data JPA Problem With Updating Multiple Entities

Spring Data JPA problem with updating multiple Entities

At this point:

@PostMapping("/postEditMenu")
public String postEdit(@ModelAttribute("newMenu")Menu menu){


menuRepository.save(menu);

return "redirect:/recipeList";
}

You receive menu from edit-page.html and it has no id, that is why it always creates new records in database.
To edit the desired menu, you would need to have it's id before.
You can create endpoint for obtaining list of menus and display them with edit button next to each menu in html site. Then if user clicks edit button redirect him to your edit form, but this time you can pass menu's id.

How to handle multiple entity update in the same transaction in Spring Data REST

Spring Data REST does not think in entities, it thinks in aggregates. Aggregate is a term coming from Domain-Driven Design that describes a group of entities for which certain business rules apply. Take an order along side its line items for example and a business rule that defines a minimum order value that needs to be reached.

The responsibility to govern constraints aligns with another aspect that involves aggregates in DDD which is that strong consistency should/can only be assumed for changes on an aggregate itself. Changes to multiple (different) aggregates should be expected to be eventually consistent. If you transfer that into technology, it's advisable to apply the means of strong consistency – read: transactions – to single aggregates only.

So there is no short answer to your question. The repository structure you show here virtually turns both ABCEntity and PQREntity into aggregates (as repositories only exist for aggregate roots). That means, OOTB Spring Data REST does not support updating them in a single transactional HTTP call.

That said, Spring Data REST allows the declaration of custom resources that can take responsibility of doing that. Similarly to what is shown here, you can simply add resources on additional routes to completely implement what you imagine yourself.

Spring Data REST is not designed to produce a full HTTP API out of the box. It's designed to implement certain REST API patterns that are commonly found in HTTP APIs and will very likely be part of your API. It's build to avoid you having to spend time on thinking about the straight-forward cases and only have to plug custom code for scenarios like the one you described, assuming what you plan to do here is a good idea in the first place. Very often requests like these result in the conclusion that the aggregate design needs a bit of rework.

PS: I saw you tagged that question with spring-data-mongodb. By default, Spring Data REST does not support MongoDB transactions because it doesn't need them. MongoDB document boundaries usually align with aggregate boundaries and updates to a single document are atomic within MongoDB anyway.

detached entity issue when updating entity spring jpa

Answer from the comments:

You pass an instance WeeklyRoutinePlan (routinePlan) to the method. I guess that this is detached, since is it loaded somewhere else. Could you try to pass the id directly as Long (routinePlan.getId()). Alternatively try to merge the routinePlan and assign the merged entity to routinePlan again.

-> So the issue is that the entity i'd created from the DTO had an ID and so it was counting as a detached entity even though i wasnt trying to save that one.

Update multiple fields of JPA Entity

Below solution worked for me:

Helper Class:

public class BeanCopy {

private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(
Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class, String.class, Date.class));

public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException
{
new BeanUtilsBean() {
@Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value != null && (primitiveTypes.contains(value.getClass()) )) {
super.copyProperty(dest, name, value);
}
}
}.copyProperties(dest, source);
}

}

This is how I copied and forced changes to database:

 try {
BeanCopy.nullAwareBeanCopy(DBcustomer,customer);
customerRepo.save(DBcustomer);

} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

Please let me know any better solution is available for the above problem.

JPA - update entity with one to many relationship array list

You explicitly call user.getPosts().clear() and yet you are surprised that only the new post exists?

You also need to be aware that userrepository.save(user) returns the merged result and you need to return that from your method to have an up-to-date representation serialized to JSON.

https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html?is-external=true#save-S-

Saves a given entity. Use the returned instance for further operations
as the save operation might have changed the entity instance
completely.

Changes:

public User updateUser(Long userid, Userdto userdto) {
User user = findByTemplatesFooterNo(userid);
User mappedUser = modelmapper.map(UserDto, User.class);

user.setName(mappedUser.getName());
user.setAge(mappedUser.getAge());

//user.getPosts().clear(); <-- WHY?
user.getPosts().addAll(mappedUser.getPost());

return userrepository.save(user); // <-- return the result of the merge
}


Related Topics



Leave a reply



Submit