I am adding RESTful support to my web application (with Spring) so I can do CRUD operations like this: Read info about a participant (JSONSerialize):
$ curl -i -H "Accept: application/json" http://localhost:8080/dancingwithstars/participant/1
{
"birthDate": "2013-01-23",
"code": "JS0001",
"firstName": "Julia",
"mainFunction": {
"code": "AA"
"name": "Principal Dancer"
},
"gender": "F",
"height": 160.00,
"id": 1,
"lastName": "Smith",
"version": 1,
"weight": 55.00
}
Or create a new participant (JSONDeserialize)
$ curl -i -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"birthDate":"2013-01-15","code":"AT0001","firstName":"Angela","mainFunction":{"code": "AB", "name":"Choreografer"},"gender":"F","height":189.00,"lastName":"Wright","version":0,"weight":76.00}' http://localhost:8080/dancingwithstars/participants
But the thing is, I don't need to know all the fields of the mainFunction object to create a participant I just need to know the code which is unique. For the serialization I can use:
return new JSONSerializer().include("mainFunction.code").exclude("mainFunction.*").exclude("*.class").transform(new DateTransformer("yyyy-MM-dd"), Date.class).prettyPrint(true).serialize(this);
And I get the following json:
{
"birthDate": "2013-01-23",
"code": "JS0001",
"firstName": "Julia",
"mainFunction": {
"code": "AA"
},
"gender": "F",
"height": 160.00,
"id": 1,
"lastName": "Smith",
"version": 1,
"weight": 55.00
}
For the deserialization I don't know. The requirement seems pretty common so I wanted to ask in the forum. Any ideas?
To sum up, there is a parent object with a reference (many-to-one) to a child object. If I provide the parent with all the information of the child, everything works fine. But hold on a second, with the ID of the child should be enough to safe the parent. I try to save the parent with just the ID of the child and then I get this exception:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
Any thoughts?
Agustin
UPDATE 27-Jan-2013: It looks like the issue comes from Hibernate. Let say we have products and categories. The relation is that products have a reference to a category (many-to-one relation). Given a category previously saved in a database. You cannot create a product and just give the ID of the category to create the product. You will need the version as well even though Hibernate won't look at the version to create the product. See below:
/*
* Create one category before the product
*/
Category cat1 = new Category();
cat1.setCode("KIT");
cat1.setName("Kitchen products");
session.save(cat1);
session.flush();
session.clear();
Category cat1db = (Category) session.get(Category.class, cat1.getCode());
logger.info(cat1.toString());
assertNotNull(cat1db.getVersion());
/*
* Create the product and assign it a category
*/
Product p1 = new Product();
p1.setName("Kettle");
p1.setPrice(4D);
Category c1 = new Category();
c1.setCode("KIT");
//c1.setVersion(new Integer(666));
p1.setCategory(c1);
session.save(p1);
session.flush();
session.clear();
Product p1db = (Product) session.get(Product.class, p1.getId());
logger.info(p1.toString());
assertNotNull(p1db.getId());
That will fail. But if you uncomment the version of the category, the product will be created. Also, Hibernate will do an extra query to the database asking for that category.
Two questions here:
- Why Hibernate needs the field version even though it doesn't look a it in the end?
- Why Hibernate does an extra query asking for the category?
Your thoughts?