[英]Deserializing a many-to-one relation with FlexJSON
我正在向我的Web應用程序添加RESTful支持(使用Spring),以便可以執行如下CRUD操作:閱讀有關參與者的信息(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
}
或創建一個新的參與者(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
但是問題是,我不需要知道mainFunction對象的所有字段來創建參與者,我只需要知道唯一的代碼即可。 對於序列化,我可以使用:
return new JSONSerializer().include("mainFunction.code").exclude("mainFunction.*").exclude("*.class").transform(new DateTransformer("yyyy-MM-dd"), Date.class).prettyPrint(true).serialize(this);
我得到以下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
}
對於反序列化,我不知道。 要求似乎很普遍,所以我想在論壇中提問。 有任何想法嗎?
綜上所述,有一個父對象帶有一個對子對象的引用(多對一)。 如果我向父母提供孩子的所有信息,則一切正常。 但是,稍等片刻,擁有孩子的ID應該足以保護父母。 我嘗試僅使用孩子的ID保存父對象,然后出現此異常:
org.hibernate.TransientPropertyValueException:對象引用了一個未保存的臨時實例-在刷新之前保存該臨時實例
有什么想法嗎?
奧古斯丁
2013年1月27日更新:問題似乎來自Hibernate。 假設我們有產品和類別。 該關系是產品具有對類別的引用(多對一關系)。 給定一個先前保存在數據庫中的類別。 您不能創建產品,而僅提供類別的ID即可創建產品。 即使Hibernate不會查看該版本來創建產品,您也將需要該版本。 見下文:
/*
* 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());
那會失敗。 但是,如果您取消注釋該類別的版本,則將創建該產品。 另外,Hibernate將對數據庫進行額外的查詢以詢問該類別。
這里有兩個問題:
你的意見?
當您使用來自JSON或外部表示形式的對象時,從Hibernate的角度來看,您始終在處理分離的對象。
自從我進行了認真的休眠以來已經有一段時間了,但是如果您要創建一個對象,那么Hibernate並不知道您必須通過將對象與會話重新連接來告訴它。 然后它將從數據庫中提取所需的信息以將其與會話相關聯,包括所有版本信息。 這被稱為分離對象,因為它是在Hibernate會話外部創建的,並且Hibernate不知道該對象是新對象還是數據庫中存在的對象。 您可以使用session.merge(someObject)重新附加對象。 您只需要重新附加父項。 為了更好的解釋:
版本信息用於樂觀鎖定。 因此,在多客戶端環境中,可能有兩個請求可以修改數據庫中的同一對象,這是程序員的職責,要求程序員對這些修改進行排序,並確保其中一個不覆蓋另一個。 樂觀鎖定是這樣做的一種方法,其中當有人修改對象版本時,為對象提供版本。 但是,在保存新版本之前,您必須檢查並確保提供給數據庫的對象與數據庫中存儲的版本相同。 這樣可以確保您要保存的模塊已在數據庫中存儲的最新版本上完成。 這意味着您不能用該對象的舊版本覆蓋該對象。 沒有該版本信息,Hibernate將無法執行樂觀鎖定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.