我正在尝试使用java将DO转换为DTO并在开始编写自己的工具之前寻找自动化工具.我只是想知道是否有相同的免费工具.
在这种情况下,您有一个客户端库传递给API的"传输对象"(POJO只有getter/setter),命名传输对象的最佳方法是什么?
package com.x.core;
public class Car {
private String make;
private String model;
public Car(com.x.clientapi.Car car) {
this.make = car.getMake();
this.model = car.getModel();
}
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,您的主类和传输对象都具有名称Car.它们在不同的包装中,但我认为使用相同的名称令人困惑.有关如何命名传输对象的最佳实践吗?
我想在微服务的背景下重新提出这个问题.这是原始问题的引用.
我目前正在为一个项目创建一个REST-API,并且正在阅读关于最佳实践的文章.许多人似乎反对DTO,只是暴露域模型,而其他人似乎认为DTO(或用户模型或任何你想称之为的)是不好的做法.就个人而言,我认为这篇文章很有意义.
但是,我也理解DTO的缺点,包括所有额外的映射代码,可能与其DTO对应物100%相同的域模型等等.
我更倾向于在我的应用程序的所有层中使用一个Object(换句话说,只是暴露域对象而不是创建DTO并手动复制每个字段).和VS代码在我的合同中的差异可以用杰克逊注释等处理@JsonIgnore或@JsonProperty(access = Access.WRITE_ONLY)或@JsonView等).或者,如果有一个或两个字段需要使用Jackson Annotation无法完成的转换,那么我将编写自定义逻辑来处理这个问题(相信我,我甚至没有遇到过这种情况,甚至在我5年多的时间里也没有休息服务的长途旅行)
我想知道我是否遗漏了没有将域复制到DTO的任何真正的不良影响
假设我有以下JPA实体:
@Entity
public class Inner {
@Id private Long id;
private String name;
// getters/setters
}
@Entity
public class Outer {
@Id private Long id;
private String name;
@ManyToOne private Inner inner;
// getters/setters
}
Run Code Online (Sandbox Code Playgroud)
Spring和Java EE都具有带有默认序列化器的REST实现,这些序列化器将实体与JSON进行编组,无需进一步编码.但是当转换Outer为JSON时,Spring和EE都嵌套了Inner它的完整副本:
// Outer
{
"id": "1234",
"name": "MyOuterName",
"inner": {
"id": "4321",
"name": "MyInnerName"
}
}
Run Code Online (Sandbox Code Playgroud)
这是正确的行为,但对我的Web服务有问题,因为对象图可以变得深/复杂并且可以包含循环引用.是否有任何方法可以配置提供的编组器以"浅"方式编组POJO /实体,而无需为每个编写器定制一个自定义JSON序列化器?一个适用于所有实体的自定义序列化程序都可以.我理想上喜欢这样的东西:
// Outer
{
"id": "1234",
"name": "MyOuterName",
"innerId": "4321"
}
Run Code Online (Sandbox Code Playgroud)
我也希望它能将JSON"解组"回到等效的java对象中.如果解决方案适用于Spring和Java EE,则可获得奖励.谢谢!
考虑使用UserDTO类和UserController公开端点来创建,更新和获取用户.
在UserDTO类中具有id属性对于创建和更新没有意义.如果我使用swagger或其他自动生成的API文档,那么它会显示id可以在create end point中传递.但系统不使用它,因为ID是在内部生成的.
如果我看看get那么可能我可以摆脱id属性,但它肯定是在列表用户端点.
我想在get/list端点返回内部用户域对象.这样我就可以从UserDTO类中删除id属性.
我可以为此采用更好的选择吗?
public class UserDTO {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<Void> create(@RequestBody UserDTO user) {
}
@RequestMapping(value = "{id}", method = RequestMethod.GET)
@ResponseBody
public …Run Code Online (Sandbox Code Playgroud) 这是一个简化的POJO我有:
@Entity
@Table( name = "Patient" )
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
(
name="Discriminator",
discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Patient implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
protected Integer ID;
@ManyToOne(targetEntity = TelephoneType.class, fetch=FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="IDPhoneType")
protected TelephoneType phoneType;
@JsonProperty(required=false, value="phoneType")
public TelephoneType getPhoneType() {
return phoneType;
}
public void setPhoneType(TelephoneType phoneType) {
this.phoneType = phoneType;
}
}
Run Code Online (Sandbox Code Playgroud)
现在这是我的班级TelephoneType:
@Entity
@Table( name = "TelephoneType" ) …Run Code Online (Sandbox Code Playgroud) 我有一种情况,我可以发送JPA实体作为休息请求和/或获得JPA实体作为休息响应
@RequestMapping(value = "/products", method = RequestMethod.POST)
public @ResponseBody ProductDetailsResponse createNewProduct(@RequestBody ProductDetails newProduct)
throws Exception {
Run Code Online (Sandbox Code Playgroud)
ProductDetails 是一个实体
@Entity
@Table(name = "product")
public class ProductDetails {
Run Code Online (Sandbox Code Playgroud)
我应该使用它,还是从实体到另一种对象进行某种转换
我正在使用Spring Boot项目,作为我目前的工具,几乎每个API我都有请求和响应类.
例如:
@RequestMapping(value = "/notice", method = RequestMethod.POST)
public AddNoticeResponse addNotice(@Valid @RequestBody AddNoticeRequest){
Notice notice = ... // creating new notice from AddNoticeRequest
noticeRepository.save(notice);
AddNoticeResponse response = ... // creating new response instance from Notice
return response;
}
Run Code Online (Sandbox Code Playgroud)
请求和响应类看起来像:
@Data
@AllArgsConstructor
public class AddNoticeRequest{
private String subject;
private String message;
private Long timeToLive;
}
Run Code Online (Sandbox Code Playgroud)
// Ommiting some annotations for brevity
public class AddNoticeResponse{
private String subject;
private String message;
private Long timeToLive;
private Date createTime; …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法将一些JPA实体导出到REST API,但是每次我想根据入口点分享一些特定的字段时,不是发送整个实体.这是一个小例子:
假设我们有一个Author几个字段的类:
@Entity
public class Author implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = SEQUENCE)
private Long id;
@NotNull
@Size(min = 1, message = "{required.field}")
private String name;
@NotNull
@Size(min = 1, message = "{required.field}")
private String country;
private LocalDate birthDate;
// getters and setters
}
Run Code Online (Sandbox Code Playgroud)
并说我们有这个REST服务(只有两种方法):
@Path("authors")
public class AuthorREST {
@Inject
private AuthorBC bc;
@GET
@Produces("application/json")
public List<Author> find(@QueryParam("q") String query) throws Exception {
List<Author> result;
if (Strings.isEmpty(query)) {
result = …Run Code Online (Sandbox Code Playgroud) 我有 JSON:
{"400" : "120Hz"}
Run Code Online (Sandbox Code Playgroud)
(实际上,我的 JSON 要复杂得多,而且基本上很大)
我用来Jackson将数据映射到FrequencyDTO.
public class FrequencyDTO {
@JsonProperty("400")
private String frequency;
public String getFreqiency() {
return this.frequency;
}
public void setFrequency(String frequency) {
this.frequency = frequency;
}
}
Run Code Online (Sandbox Code Playgroud)
之后,我需要将此 DTO 发送到前端,但我希望它的字段是人类可读的,例如:{"frequency_value" : "120Hz"}。
我唯一想到的就是创建某种FrequencyFrontendDTO,例如:
public class FrequencyFrontendDTO {
@JsonProperty("frequency_value")
public String frequency;
//getters and setters
}
Run Code Online (Sandbox Code Playgroud)
并将其映射为FrequencyDTO.
有没有更干净的方法来做到这一点?
我面临 API 设计问题。考虑以下流程:
正如您所看到的,我有 2 个类来代表我的模型(SomethingDTO和SomethingResponse),还有 2 个类来代表第 3 方模型(3rdPartyRequest和3rdPartyResponse)。我正在使用映射器提供从 3rdPARty 模型类到我的模型类的转换。
问题是:这 4 个类都具有完全相同的属性。
我应该在所有这些类中重复这些属性吗?我应该在整个流程中只使用一个 DTO 类吗?
解决这个问题的最佳实践(或模式)是什么?
谢谢
考虑一个名为 的大实体entity。它公开了 100 种不同的更新操作,包括添加和删除属性、更新属性等。
使用单个 URI 和应用程序服务器路由处理的许多情况之间应该优先选择什么:
PATCH /entity/[id] {"type":"a","key1":"val1","key2":"val2"} or
{"type":"b","key3":"val3","key4":"val4"} or ...
Run Code Online (Sandbox Code Playgroud)
...并且使用许多 URI,每个应用程序服务器路由处理一种情况:
PATCH /entity/[id]/a {"key1":"val1","key2":"val2"}
PATCH /entity/[id]/b {"key3":"val3","key4":"val4"}
Run Code Online (Sandbox Code Playgroud)
或者也许使用PUT?需要更新(非常)部分实体。
考虑到 REST 合规性、负载均衡器、缓存、KISS 等,最好的方法是什么。任何想法将不胜感激。
java ×10
rest ×7
jpa ×4
dto ×2
hibernate ×2
jackson ×2
spring ×2
spring-mvc ×2
api-design ×1
http ×1
java-ee ×1
jax-rs ×1
jersey-2.0 ×1
json ×1
lazy-loading ×1
mapping ×1
spring-boot ×1
web-services ×1