您是直接通过 http 传递 hibernate / jpa 实体对象还是有更好的选择?

Do you directly pass hibernate / jpa entity-objects via http or is there an better alternative?

首先,我想声明我对这个 JPA/Hibernate 还是个新手,而且 micronaut 对我来说也是新手(我在 PHP、Python 方面有很多经验) , "Desktop Java", C++ 等)。

当我通过 micronaut @Body 注释传递实体时,我无法摆脱我误解概念中某些东西的感觉,因为它们是分离的,我必须使用手动将它们合并到持久性上下文中em.merge(entity).

请考虑以下示例(缩短以仅显示重要部分):

MyEntity.java:

import javax.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Table(name = "entities")
@Getter
@Setter
@ToString
public class Entity{
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Long id;

    @Column
    protected String name;
}

MyController.java:

import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.*;

@Controller("/entities")
public class EntitiyCrudController {

    @Inject
    private final EntityManager entityManager;

    @Post("/create")
    public HttpResponse create(@Body Entity entity) {
        try {
            entity = entityManager.merge(entity);
            return HttpResponse.ok(entity);
        } catch (ConstraintViolationException exception) {
            return HttpResponse.badRequest();
        }
    }

}

请注意,样本只是一起复制,所以可能会有一些错误,但我认为这是一个关于正确选择方法的问题。

在我的研究过程中,到目前为止我看到的所有示例都是关于未分离的持久实体。有时我看到人们使用 DTO(实体 classes 在 属性 级别上的精确副本,但没有 jpa / hibernate 注释)。我认为这种方法也有一些味道,因为我必须构建一个具有完全相同属性的全新 class。

如果没有将 dto 的属性转移到实体(调用 dto getter,调用实体 setter),我使用 DTO 不会有什么大问题。有没有一种 "clean" 方法可以做到这一点而无需手动传输每个 属性 (可能是一些基于反射的库或注释处理器)。然后我可以通过 dto id 从持久性上下文加载一个实体,然后更新我的实体字段并触发更新。

总而言之,我的问题是: - 直接传递实体会导致实体被分离(因此,例如 micronaut-data 包不能以这种方式进行更新) - 使用 DTO 最终会通过 属性 复制 属性,这非常冗长

那么通过 json 将对象发布到网络服务器并保存或更新它的正确方法是什么?

如果有什么不明白的地方,我很乐意澄清!

IMO DTO 方法是将数据从持久层传递到 UI 层的方法。 尝试使用 Dozer 实体复制器 (https://www.baeldung.com/dozer)。这将帮助您减少从一个实体复制到另一个实体的大量样板代码。

您描述的方法本身并没有错。但是你必须知道你在做什么,你正在将你的休息接口与你的数据库实现相结合。根据您的要求,这可能是个问题。例如,如果您的应用程序需要开放式并发,则需要在您的实体中添加一个@Version 字段,您将通过 Web 服务自动公开此信息。

通常您想要控制公开的数据,并且通常您想要解耦其余数据的 DB 实现 API。顺便说一下,通常您还希望拥有一个具有用于验证的业务逻辑、业务规则的域对象...