簡體   English   中英

使用FlexJSON反序列化多對一關系

[英]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將對數據庫進行額外的查詢以詢問該類別。

這里有兩個問題:

  1. 為什么Hibernate最終看起來並不需要字段版本?
  2. 為什么Hibernate會額外查詢該類別?

你的意見?

當您使用來自JSON或外部表示形式的對象時,從Hibernate的角度來看,您始終在處理分離的對象。

自從我進行了認真的休眠以來已經有一段時間了,但是如果您要創建一個對象,那么Hibernate並不知道您必須通過將對象與會話重新連接來告訴它。 然后它將從數據庫中提取所需的信息以將其與會話相關聯,包括所有版本信息。 這被稱為分離對象,因為它是在Hibernate會話外部創建的,並且Hibernate不知道該對象是新對象還是數據庫中存在的對象。 您可以使用session.merge(someObject)重新附加對象。 您只需要重新附加父項。 為了更好的解釋:

在Hibernate中重新附加分離對象的正確方法是什么?

版本信息用於樂觀鎖定。 因此,在多客戶端環境中,可能有兩個請求可以修改數據庫中的同一對象,這是程序員的職責,要求程序員對這些修改進行排序,並確保其中一個不覆蓋另一個。 樂觀鎖定是這樣做的一種方法,其中當有人修改對象版本時,為對象提供版本。 但是,在保存新版本之前,您必須檢查並確保提供給數據庫的對象與數據庫中存儲的版本相同。 這樣可以確保您要保存的模塊已在數據庫中存儲的最新版本上完成。 這意味着您不能用該對象的舊版本覆蓋該對象。 沒有該版本信息,Hibernate將無法執行樂觀鎖定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM