we're building a REST-API using Spring MVC 3.2, Jackson 1.9.12, Hibernate 4.2.2.
Yesterday I needed to pass a small object graph to the API, which should get persisted in the database. It some kind of works and I could build workarounds for those problems, but I think there must be a nicer solution.
So here is what we have:
- Class
Bill - Class
Contact - Class
Address - Class
Item
Relations are:
Billhas twoOneToOnerelations toContact. One calledsender, one calledreceiver.Billhas aManyToOnerelation toItem, calleditem.Contacthas aOneToOnerelation toAddress, calledaddress.
(This may seem a bit dumb, but I left out some fields and other relations, to bring the problem to the point)
First Problem - Simple case - Overriding database entries:
Let's ignore all those dependencies and relations and just take the plain Bill class. If there's an incoming JSON request which doesn't contain an object id everything works as expected and Spring/Hibernate creates a new entry in database:
{ ...
"createdAt":"2013-05-29"
}
But if I specify an id in the JSON request, Spring/Hibernate will update the row containing the given id:
{ ...
"id":"c5a562d0-c8ab-1c42-8399-080012345678"
"createdAt":"2013-05-29"
}
If I specify an id in the JSON request, but that id doesn't exist in database, it will create a new entry.
The code I use is nothing special. Here's the controller action:
@RequestMapping(value = "/create", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.CREATED)
public Bill create(@RequestBody Bill bill) {
bill = service.createBill(bill);
return bill;
}
And the service method:
@PreAuthorize("isAuthenticated()")
@Transactional
public Bill createBill(Bill bill) {
bill = billDao.store(bill);
return bill;
}
As you can see, I'd like to use the /create path to create new entries and not update already existing ones. As a workaround I could of course use setId(null) in the first line of the controller action, but is there any nicer/better way?
Second Problem - Another id thing - How to correctly design entities?
We again have the object graph from above:
"bill":{ ...
"sender":{ ...
"address":{ ... }
},
"receiver":{ ...
"address":{ ... }
},
"item":{ ... }
}
There's a logical difference between Contact(and Address) and Item:
- A
Contact(andAddress) consists of a bunch of new data. Means: The GUI will display a lot input fields, which the user has to fill in. - An
Itemis already in the database, and I basically would just need itsid, not the whole object. This means: The GUI will display a dropdown list with all existingItems and the user has to choose one of them.
Now of course I'd like to use (and reuse) my entities, but my Bill entity for example expects an Item object, not an item_id. As a workaround I could of course create another bean, which is nearly the same as the Bill class, but instead of item it contains an item_id:
"the_new_special_bill_for_incoming_json":{ ...
"sender":{ ...
"address":{ ... }
},
"receiver":{ ...
"address":{ ... }
},
"item_id":{ ... }
}
So again, the same question: Is there a nicer/better way?
Thank you guys!