REST和数据库的对象命名约定

如何解决REST和数据库的对象命名约定

在使用Java的REST API构建CRUD应用程序时,我一直在不断创新,我正在寻找某种适用的标准。

让我们以示例的方式进行。假设我有一个“用户”表和这些REST端点:

GET  /users/{user_id} // returns a user
POST /users           // creates a user
PUT  /users/{user_id} // updates a user

在每种方法中,我必须选择,插入或更新数据库中的用户。

对于这六个操作中的每个操作(REST操作3个,数据库操作3个),我需要通过REST传入或发送到数据库的“用户” POJO的不同属性集。

例如,在REST端,创建用户时,我不需要user_id(因为它是由数据库创建的),但是我确实需要密码。获取用户时,我确实需要user_id,但我永远不想将密码返回给客户端。更新用户时,我可能要忽略一些字段,因为它们是只读的(例如用户名或创建日期)。

在数据库方面,我可能需要不同的字段,这些字段不会在REST API中传递回去,例如“ is_approved”或“ some_secret”。而且我经常需要创建派生字段,例如“ password_hash”。

因此,正如我所说,同一件事的六个不同表示形式。在Java中,我通过制作六个不同的POJO类来做到这一点。并不总是需要那么多独特的类,但有时却需要。

在REST API中,我不想对所有端点使用相同的类,而只是忽略某些字段,因为该类已传递给我们的API文档工具并且其属性已发布。

这六个类是否有标准的命名约定?

过去,对于REST,我曾使用过CreateUser,GetUser和UpdateUser。我不喜欢这些名称,因为它们是动词,应该是名词。

UserForCreation和UserForUpdate很尴尬。 NewUser和ModifiedUser可能不错,但是我不知道如何调用GET用户。

在数据库端,我还需要另外一套完整的名称。

对于这种事情,肯定有一个标准或约定。有人知道这是什么吗?

解决方法

我认为您通常对每个请求和响应都具有特定对象的想法是正确的;但是,根据API的设计,您实际上只需要一个User类。您可以使用构建器来抽象出创建逻辑(例如生成用户ID),并将请求对象传递到位于REST端和数据库之间的DAO中。 DAO将仅接受请求,检索用户数据,构建并返回User对象。

一旦创建了用户对象,便可以将其用于创建响应对象,该对象将被序列化并放入响应数据中。最好编写两个用户类(类似UserInternalUser),以便更明确地向客户端公开哪些数据,尤其是在写入客户端的情况下。与API相同的库。您无法实现额外的InternalUser并无法在响应对象构建器,工厂或构造器中处理字段过滤;但是,如果客户端是在同一库中编写的,则可能会泄漏敏感或必要的信息。

您可能希望查看Swagger个文件。该标准提供了一个很好的REST Api规范,该规范非常简单,并提供了一种模板化API结构的好方法,即使它们经常看起来像json或xml的墙一样。

tl;博士 (根据@Turing85

的建议
  • CreateUser [请求|响应]
  • GetUser [请求|响应]
  • UpdateUser [请求|响应]
  • 用户
  • InternalUser
,

此方法受到HexagonalArchitecture / Clean Architecture / Ports and Adapters的借鉴/启发。由于我们已经将DTO和业务对象完全分开,因此我们非常接近上述架构。在“干净架构”中,鲍伯叔叔谈到了“用例”。每个用例都有一些输入和一些输出。我们可以将输入想象成对用例的 request ,将输出看作对给定请求的 response 。因此,对于业务实体User以及creategetupdate等的用例,...其中一个这样的实体,我建议使用以下命名模式:

<use-case><Business-entity>[Request|Response]

对于给定的示例,这意味着我们将创建类

  • CreateUserRequestCreateUserResponse
  • GetUserRequestGetUserResponse
  • UpdateUserRequestUpdateUserResponse

更重要的是:对于CreateUpdate之类的复杂操作,我们可以提取公共字段并将它们放在超类中(如果只有Java具有多重继承性,我们可以使用mixins ... ),只留下实际的用例请求数据来定义我们真正需要的数据。在许多情况下,响应是相同的,因此有意义的是使用通用的UserResponse类而不是许多不同的响应。这提供了一致的API响应的额外好处,例如如果要返回用户列表,则可以返回List<UserResponse>(可能还有一些分页信息)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-