Search code examples
springrestspring-bootspring-data-restorphan

POST entity with its sub-resources as one transaction OR strategy for orphan removal


I have a spring boot rest api. I have conceptually 2 entities named Venue and Address, where a Venue MUST have one Address. My problem is that I have to POST an Address entity first and then POST my Venue entity with the self link of the Address entity. This seemed okay until I began to code my browser client. I don't like the fact that if, once the Address has been persisted to the database, something happened to break the users connection before the Venue is persisted I would end up with a junk entity in my database as it wouldn't be associated with anything. I can code my clients to rollback in these situations by deleting the Address that was just created but then if my api is used by a third party then I've got a problem. Is there any way that i can post all my sub-resource data at the same time as POSTing the parent entity? If not, are there any common strategies to sweep up orphaned records?


Solution

  • Here are a few options to ponder.

    If the same Address is POST'd twice, then there should not be two records in the DB for it. The way to ensure this is to normalize the Address input then check if that Address has already been added. If it has already been added return either a 409 conflict or 200 OK. If a new Address is in fact created, then you can return a 201 CREATED. You would have to normalize the data first so that multiple variations of the same Address do not cause multiple entries. For example when normalizing turn all "Smith St." and "smith street" and "Smith Str." into "SMITH STREET". You can apply this logic to all the fields in the Address. Then you can check if that Address is already in the DB.

    If this is too much work, then consider not having Address be its own table/collection in the DB. Maybe just have Address be a field in Venue. If at some point the code needs to take an Address from a Venue and put it into its own table, then that can happen as needed when it comes up.

    Another idea is to have a service that takes both Venue and Address as input. Maybe you can call it VenueRequest. This object will contain two main fields, Venue and Address. The service will do the job of storing to the DB the Address then the Venue.