如何在Spring Boot中避免DTO与领域对象之间的相互转换?

huangapple go评论72阅读模式
英文:

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:

&lt;form:form id=&quot;parcelCondemnationCaseDetailsForm&quot;
modelAttribute=&quot;parcelCondemnationCaseDetailsDTO&quot;&gt;
&lt;form:hidden path=&quot;prclSeqNum&quot; /&gt;
&lt;form:hidden path=&quot;condemnationStatusCode&quot; /&gt;
&lt;form:hidden id=&quot;isMDOTVerifiedMoveDateAvailable&quot;
	path=&quot;mDOTVerifiedMoveDateAvailable&quot; /&gt;
&lt;div class=&quot;form-group&quot;&gt;
	&lt;div class=&quot;row&quot;&gt;
		&lt;div class=&quot;col-md-3&quot;&gt;
			&lt;label for=&quot;finalDisposition&quot;&gt;Final Disposition&lt;/label&gt;
			&lt;form:select class=&quot;form-control dirty _enableSaveDisable&quot;
				id=&quot;finalDisposition&quot; path=&quot;finalDisposition&quot;
				disabled=&quot;${agSecurityFinalDisabled}&quot;
				onchange=&quot;finalDispositionChange()&quot;&gt;
				&lt;form:option value=&quot;&quot; select=&quot;select&quot;&gt;Select&lt;/form:option&gt;
				&lt;form:option value=&quot;J&quot;&gt;Judgement&lt;/form:option&gt;
				&lt;form:option value=&quot;V&quot;&gt;Jury Verdict&lt;/form:option&gt;
				&lt;form:option value=&quot;S&quot;&gt;Settlement&lt;/form:option&gt;
				&lt;form:option value=&quot;O&quot;&gt;Other&lt;/form:option&gt;
			&lt;/form:select&gt;
		&lt;/div&gt;
		&lt;div class=&quot;col-md-3&quot; id=&quot;finalDispositionDescriptionDiv&quot;
			style=&quot;display: none;&quot;&gt;
			&lt;label for=&quot;finalDispositionDescription&quot; class=&quot;req-label&quot;&gt;Final
				Disposition Description&lt;/label&gt;
			&lt;form:input type=&#39;text&#39; id=&quot;finalDispositionDescription&quot;
				class=&quot;form-control dirty _enableSaveDisable&quot; aria-required=&quot;true&quot;
				path=&quot;finalDispositionDescription&quot; maxlength=&quot;50&quot;
				disabled=&quot;${agSecurityFinalDisabled}&quot; /&gt;
		&lt;/div&gt;
		&lt;div class=&quot;col-md-3&quot;&gt;
			&lt;label for=&quot;finalDispositionDate&quot;&gt;Final Disposition Date&lt;/label&gt;
			&lt;form:input type=&#39;text&#39; id=&quot;finalDispositionDate&quot;
				class=&quot;form-control lamdaDate dirty _addDate _pastPresent _enableSaveDisable&quot;
				path=&quot;finalDispositionDate&quot; disabled=&quot;${agSecurityFinalDisabled}&quot; /&gt;

		&lt;/div&gt;
		&lt;div class=&quot;col-md-3&quot;&gt;
			&lt;label for=&quot;closedDate&quot;&gt;Closed Date &lt;/label&gt;
			&lt;form:input type=&#39;text&#39; id=&quot;closedDate&quot;
				class=&quot;form-control lamdaDate dirty _addDate _pastPresent  _enableSaveDisable&quot;
				path=&quot;closedDate&quot; disabled=&quot;${agSecurityFinalDisabled}&quot; /&gt;

		&lt;/div&gt;
	&lt;/div&gt;&lt;/form:form&gt;

and this is my controller

	@PostMapping(&quot;/saveCaseDetails.htm&quot;)
public @ResponseBody String saveCaseDetails(ParcelCondemnationCaseDetailsDTO parcelCondemnationCaseDetailsDTO,
		ModelMap model) {
	String responseMessage = &quot;&quot;;
	try {
		parcelCondemnationCaseDetailsDTO = parcelCondemnationCaseDetailsService
				.saveCaseDetails(parcelCondemnationCaseDetailsDTO);
		responseMessage = &quot;success&quot;;
	} catch (Exception e) {
		log.error(
				&quot;Error occured while saving Condemnation &gt; Valuation at CondemnationValuationController.saveValuation&quot;,
				e);
		responseMessage = &quot;Error occured while saving Case Details.&quot;;
	}
	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(&quot;/saveCaseDetails.htm&quot;)
    @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&#39;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>



huangapple
  • 本文由 发表于 2020年9月15日 03:30:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63890758.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定