我使用JPA定义了下表:
@Data
@Entity
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true)
private String name;
private Integer budget;
private String description;
private Boolean isArchived;
private LocalDate archivedDate;
@Transient
private Integer usedBudget;
@NotNull
@ManyToOne
private Customer customer;
}
我有一个REST-API方法
getProjects()
,它从数据库返回所有项目。 usedBudged
不会持久存储在数据库中,必须进行计算。在大多数情况下,当我呼叫getProjects()
时,我不需要usedBudget
属性。但是在一种情况下,我想计算项目的usedBudget
并将其直接与项目对象一起发送,因此我不必先获取所有项目并为每个项目进行单独的API调用即可获取usedBudget
。因此,为了实现这一点,我向Project实体添加了一个usedBudget
属性,并将其标记为瞬态。这样,它就不会持久保存在数据库中,每当我想要获取usedBudget
时,我都会在返回项目对象之前对其进行计算并进行设置。唯一的问题是,即使未设置(null),也无法通过JSON发送。有什么方法可以忽略/不发送此瞬态值,只要将其设置为null?解决我的问题的另一种方法是使用帮助程序类,该类扩展Project并具有一个附加属性
usedBudget
。因此,每当我需要usedBudget
时,我都将返回helper类,而每当不这样做时,我都将仅返回正常项目(在这种情况下,没有瞬态usedBudget属性)。这样,我将永远不会发送无用的null值。哪种方法更好,也许有更好的方法?
最佳答案
您应该在持久化的对象(实体)与REST api服务的对象之间有清晰的区分:它们称为DTO。例如:
@Data
public class ProjectDTO {
private long id;
private String name;
private Integer budget;
private String description;
private Boolean isArchived;
private LocalDate archivedDate;
private Customer customer;
}
但是,如果在特定情况下需要返回使用了预算的项目,则可以使用以下DTO:
@Data
public class ProjectWithBudgetDTO extends ProjectDTO {
private Integer usedBudget;
}
当然,从实体创建dto需要一些工作,但这非常简单。
这样,API就与持久数据模型脱钩,从而使它们能够以不同的方式发展。例如,您可以打扰其余api客户端,从而向数据库中添加新字段。甚至删除一个字段,并在DTO中保留默认值。