3

The company I work for is converting over to Spring Data and most of us are still learning. I keep running into a problem that I cant quite wrap my head around. How to handle saving or updating an entity that has a relationship to detached entities where values in those entities might need to change.

I have service, rate_plan, and service_rate_plan tables. the rate_plan table joins the service and rate_plan tables and it has a column for the cost of the service in that rate plan.

Lets assume that a user wants to create a Rate Plan. I create a Rate Plan DTO and add to it a list of all possible serviceRatePlan. I present this to the user. The user then adds information for the Rate Plan and sets cost for 1 or more of the services and submits the form.

Now I have a Rate Plan DTO with some information filled in and a list of serviceRatePlan that may or may not have a cost.

For an update the current practice at my company is fetch a list of the serviceRatePlan and iterating it and the new list updating the existing list with the new information.

That just doesn't seem right to me. If the service list of was 10 items I guess it might be ok. But if the list was 1000 items or something like that it would, seem to me, to be really inefficient.

So what is the correct, most efficient, way of doing this?

This is an example of how I am currently merging i

protected void buildServiceListFromDto(RatePlan ratePlan, List<RatePlanServiceClassDto> serviceClasses)
{
  Set<ServiceRatePlan> servicesForRatePlan = new HashSet<>();
  ratePlan.setServicesForRatePlan(servicesForRatePlan);

  if (serviceClasses != null)
  {
    for (RatePlanServiceClassDto serviceClassDto : serviceClasses)
    {
      if (serviceClassDto.getServices() != null)
      {
        for (RatePlanServiceDto serviceDto : serviceClassDto.getServices())
        {
          /*
           * Looking at the servrate table it looks as though empty values are not stored.
           */
          if (StringUtils.isNotEmpty(serviceDto.getAmount().toString()))
          {
            ServiceRatePlan serviceRatePlan = new ServiceRatePlan();
            serviceRatePlan.setAmount(serviceDto.getAmount().getValue());
            serviceRatePlan.setRatePlan(ratePlan);
            Service service = serviceRepository.findOne(serviceDto.getNumber());
            serviceRatePlan.setService(service);
            servicesForRatePlan.add(serviceRatePlan);
          }
        }
      }
    }
  }
}
RhythmicDevil
  • 705
  • 5
  • 15
  • 31
  • 1
    I added the spring-data-jpa tag since it sounds like this is what you are talking about. Feel free to revert and replace it with the correct tag if this was wrong. – Jens Schauder Mar 08 '17 at 05:55

1 Answers1

1

Assuming you refer to Spring Data JPA.

The right thing to do here is to use the features of JPA, namely the cascade configurations. Set the cascade option of the references from RatePlan to ServiceRatePlan to Cascade.ALL and JPA will take care of saving them when you save the RatePlan.

You can start here for more information about cascade: JPA @ManyToOne with CascadeType.ALL

When deciding on what relationships you want to cascade it helps to think in Aggregate Roots as you might them from Domain Driven Design. The idea is that you have aggregates of closely related entities. In your case RatePlan and ServiceRatePlan. Each Aggregate has one Aggregate Root, in your case RatePlan. You then have repositories only for Aggregate Roots and all the elements connected to that root via cascade so you don't need repositories for those. See also http://static.olivergierke.de/lectures/ddd-and-spring/#ddd.building-blocks.aggregates

Community
  • 1
  • 1
Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • The term "Aggregate Root" is very useful to me, thank you. I guess looking back at my question the main thing I am trying to figure out is the most efficient way to merge the incoming changes. I have a list that represents the relationships between the Rate Plan and Services. The list needs to be updated with the incoming changes. Existing cost might change, new relationships might be added, and existing ones might be removed. I have pasted into the original question the method I am using to merge the data. – RhythmicDevil Mar 08 '17 at 13:32