英文:
How to avoid DTO to domain conversion and vice versa in Spring boot?
问题
在我的项目中,我从用户界面获取值,传递给控制器再到服务层。然后我进行DTO到领域对象的转换,但我觉得这是不必要的,并且不是一个好的设计。
例如,这是我的 JSP 页面:
<form:form id="parcelCondemnationCaseDetailsForm" modelAttribute="parcelCondemnationCaseDetailsDTO">
<form:hidden path="prclSeqNum" />
<form:hidden path="condemnationStatusCode" />
<form:hidden id="isMDOTVerifiedMoveDateAvailable" path="mDOTVerifiedMoveDateAvailable" />
<div class="form-group">
<div class="row">
<div class="col-md-3">
<label for="finalDisposition">Final Disposition</label>
<form:select class="form-control dirty _enableSaveDisable"
id="finalDisposition" path="finalDisposition"
disabled="${agSecurityFinalDisabled}"
onchange="finalDispositionChange()">
<form:option value="" select="select">Select</form:option>
<form:option value="J">Judgement</form:option>
<form:option value="V">Jury Verdict</form:option>
<form:option value="S">Settlement</form:option>
<form:option value="O">Other</form:option>
</form:select>
</div>
<!-- Other form fields ... -->
</div>
</div>
</form:form>
这是我的控制器:
@PostMapping("/saveCaseDetails.htm")
public @ResponseBody String saveCaseDetails(ParcelCondemnationCaseDetailsDTO parcelCondemnationCaseDetailsDTO,
ModelMap model) {
String responseMessage = "";
try {
parcelCondemnationCaseDetailsDTO = parcelCondemnationCaseDetailsService
.saveCaseDetails(parcelCondemnationCaseDetailsDTO);
responseMessage = "success";
} catch (Exception e) {
log.error("Error occured while saving Condemnation > Valuation at CondemnationValuationController.saveValuation",
e);
responseMessage = "Error occured while saving Case Details.";
}
return responseMessage;
}
这是服务层:
@Override
public ParcelCondemnationCaseDetailsDTO saveCaseDetails(ParcelCondemnationCaseDetailsDTO parcelCondemnationCaseDetailsDTO) {
ParcelCondemnation parcelCondemnation = ParcelCondemnationCaseDetailsMapper.INSTANCE
.getCaseDetails(parcelCondemnationCaseDetailsDTO);
parcelCondemnationRepository.save(parcelCondemnation);
}
我认为在进行DTO到领域对象的转换时,并没有添加任何价值。那么,我的问题是是否有方法可以避免使用DTO、映射器和额外的代码呢?
谢谢查阅。
英文:
In my project I am getting values from UI, passing to Controller and to the service layer. Then I do the DTO to domain conversion, I feel that this is unnecessary and not a good design.
e.g. Here is my JSP:
<form:form id="parcelCondemnationCaseDetailsForm"
modelAttribute="parcelCondemnationCaseDetailsDTO">
<form:hidden path="prclSeqNum" />
<form:hidden path="condemnationStatusCode" />
<form:hidden id="isMDOTVerifiedMoveDateAvailable"
path="mDOTVerifiedMoveDateAvailable" />
<div class="form-group">
<div class="row">
<div class="col-md-3">
<label for="finalDisposition">Final Disposition</label>
<form:select class="form-control dirty _enableSaveDisable"
id="finalDisposition" path="finalDisposition"
disabled="${agSecurityFinalDisabled}"
onchange="finalDispositionChange()">
<form:option value="" select="select">Select</form:option>
<form:option value="J">Judgement</form:option>
<form:option value="V">Jury Verdict</form:option>
<form:option value="S">Settlement</form:option>
<form:option value="O">Other</form:option>
</form:select>
</div>
<div class="col-md-3" id="finalDispositionDescriptionDiv"
style="display: none;">
<label for="finalDispositionDescription" class="req-label">Final
Disposition Description</label>
<form:input type='text' id="finalDispositionDescription"
class="form-control dirty _enableSaveDisable" aria-required="true"
path="finalDispositionDescription" maxlength="50"
disabled="${agSecurityFinalDisabled}" />
</div>
<div class="col-md-3">
<label for="finalDispositionDate">Final Disposition Date</label>
<form:input type='text' id="finalDispositionDate"
class="form-control lamdaDate dirty _addDate _pastPresent _enableSaveDisable"
path="finalDispositionDate" disabled="${agSecurityFinalDisabled}" />
</div>
<div class="col-md-3">
<label for="closedDate">Closed Date </label>
<form:input type='text' id="closedDate"
class="form-control lamdaDate dirty _addDate _pastPresent _enableSaveDisable"
path="closedDate" disabled="${agSecurityFinalDisabled}" />
</div>
</div></form:form>
and this is my controller
@PostMapping("/saveCaseDetails.htm")
public @ResponseBody String saveCaseDetails(ParcelCondemnationCaseDetailsDTO parcelCondemnationCaseDetailsDTO,
ModelMap model) {
String responseMessage = "";
try {
parcelCondemnationCaseDetailsDTO = parcelCondemnationCaseDetailsService
.saveCaseDetails(parcelCondemnationCaseDetailsDTO);
responseMessage = "success";
} catch (Exception e) {
log.error(
"Error occured while saving Condemnation > Valuation at CondemnationValuationController.saveValuation",
e);
responseMessage = "Error occured while saving Case Details.";
}
return responseMessage;
}
and the service layer.
public ParcelCondemnationCaseDetailsDTO saveCaseDetails(
ParcelCondemnationCaseDetailsDTO parcelCondemnationCaseDetailsDTO) {
ParcelCondemnation parcelCondemnation = ParcelCondemnationCaseDetailsMapper.INSTANCE
.getCaseDetails(parcelCondemnationCaseDetailsDTO);
parcelCondemnationRepository.save(parcelCondemnation);
I do not see that I am adding any value while doing DTO to domain conversion.
So, my question is there any way I can just avoid using DTO, mappers and extra line of code?
Thanks for looking.
答案1
得分: 2
由于您的实体恰好是您的DTO,您可以在控制器中使用@JsonView
注解,并直接在实体类中使用,该注解可以过滤您希望作为响应显示在UI中的字段。
@PostMapping("/saveCaseDetails.htm")
@JsonView(View.Public.class)
public @ResponseBody String saveCaseDetail
...
@Entity
public ParcelCondemnation {
@JsonView(View.Public.class)
private String anyFieldtoShow;
private String anyFieldToNotShow;
...
public class Views {
public static class Public {}
}
在这种情况下,您的响应将仅显示`anyFieldToShow`作为对带有相关`JsonView`注解的端点的任何请求的答案。
以下是更详细的说明:
[Baeldung教程][1]
我知道您可能会使用GraphQL,不幸的是,我对此了解不够,但是以下是链接,如果您希望深入了解:[GraphQL文档][2]
[1]: https://www.baeldung.com/jackson-json-view-annotation
[2]: https://graphql.org/code/#java
<details>
<summary>英文:</summary>
Since your Entity is exactly your DTO, you can use `@JsonView` annotation in your controller and directly in your entity class, which can filter the fields you wish to show to your UI as response.
@PostMapping("/saveCaseDetails.htm")
@JsonView(View.Public.class)
public @ResponseBody String saveCaseDetail
...
@Entity
public ParcelCondemnation {
@JsonView(View.Public.class)
private String anyFieldtoShow;
private String anyFieldToNotShow;
...
public class Views {
public static class Public {}
}
In this case, your response will show only the `anyFieldToShow` as an answer to any request to that enpoint annotated with the related `JsonView`.
Here is a better explanation:
[Baeldung tutorial][1]
And I know you can maybe use GraphQL, which unfortunately I don't have enough knowledge to talk about, but here it follows the link if you wish to go deep: [GraphQL doc][2]
[1]: https://www.baeldung.com/jackson-json-view-annotation
[2]: https://graphql.org/code/#java
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论