使用DTO需要一定的開銷:必須創建DTO類;實體類必須在序列化之前映射到DTO。
只要他們似乎違背了「不要重複自己」的原則,DTO也會「感覺不對」。看到一個實體和一個DTO並看到它們本質上是相同的,這是令人沮喪的。
因此,直接暴露您的JPA實體會減少代碼並減少處理代碼時的精神開銷。您的控制器,服務和存儲庫都處理相同的類。
有問題,但是:要公開給API用戶的內部表示與接口之間
不匹配。
真實世界的例子:根文檔是article
和子文檔是sections
的分層文檔。在內部,每個文檔都與可能爲空的父文檔有關係。
直接通過REST接口公開此實體將要求客戶端發送id
(或HATEOAS中的url
)作爲其提交實體的一部分,以正確地將文檔鏈接在一起。
更好的辦法是在創建子部分時將api用戶POST設置爲/articles/{id}/sections/
。
公開內部數據。
您的實體可能包含標識符,磁盤上的路徑等,這些標識符並非真正用於公共消費。在序列化時,你將不得不@JsonIgnore
這些。當反序列化時,您也可以手動填寫實體。
表現。
與上述相似;也許你的實體包含一個大型數據對象。您希望用戶能夠POST或PUT這些,但不應要求他們下載對象只是爲了讀取實體的其他字段。
潛在的序列化問題。
延遲加載的集合是這裏經典的失敗案例。
比需要更復雜的序列化表示。
真實世界的例子:word
實體集合synonyms
;同義詞依賴於這個詞。直接序列化的實體將導致:
{ "id":12,
"word": "cat",
"synonyms": [
{ "id": 23,
"synonym": "kitty"
},
{ "id": 34,
"synonym": "pussycat"
}
]
}
更好的模式是:在同一類可降低清晰度
{ "word": "cat",
"synonyms": [
"kitty",
"pussycat"
]
}
大量的註釋。
根據您的實體的複雜性,你可能有JPA的註解(@Entity
,@Id
,@GeneratedValue
,@Column
,@ManyToMany
,@MappedBy
等),XML註釋(@XmlRootElement
,@XmlType
,@XmlElement
,等等),JSON註解(@JsonInclude
,@JsonIgnore
, @JsonProperty
等)和驗證註釋(@NotNull
,@Null
等)都在同一個類上。
由於所有這些問題,我通常使用DTO。我手工將這個實體做成DTO映射,但有一些項目試圖使這更容易,如Dozer。
我可以想象使用spring-data-rest
或直接暴露我的實體,只是在我有非常簡單的實體,沒有太多關係,以及實體模型和我希望的模型之間高度一致的情況下暴露給用戶。
您的至少一些問題至少沒有解決https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra#projections-in-spring-數據休息 –