您是直接通过http传递hibernate/jpa实体对象,还是有更好的选择? 首先,我想说的是,我对JPA/Hibernate这一类事物还很陌生,而且MixOnter对我来说是新的(我有很多经验,例如PHP、Python、“桌面java”、C++等)。

您是直接通过http传递hibernate/jpa实体对象,还是有更好的选择? 首先,我想说的是,我对JPA/Hibernate这一类事物还很陌生,而且MixOnter对我来说是新的(我有很多经验,例如PHP、Python、“桌面java”、C++等)。,java,hibernate,jpa,micronaut,micronaut-data,Java,Hibernate,Jpa,Micronaut,Micronaut Data,当我通过micronaut@Body注释传递实体时,我无法摆脱这样一种感觉:我误解了概念中的某些内容,因为它们是分离的,我必须使用em.merge(entity)手动将它们合并到持久性上下文中 请考虑以下示例(缩短为仅显示重要部分): MyEntity.java: import javax.persistence.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Entity @Table(name

当我通过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(属性级别上实体类的精确副本,但没有jpa/hibernate注释)。我认为这种方法也有一些味道,因为我必须构建一个具有完全相同属性的全新类

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

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

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


如果有什么不可理解的,我很乐意澄清

IMO DTO方法是将数据从持久性层传递到UI层的方法。
尝试使用推土机实体复印机()。这将帮助您减少从一个实体复制到另一个实体的大量锅炉板代码。

您描述的方法本身没有任何错误。但是您必须知道您正在做什么,您正在将rest接口与DB实现耦合。这可能是一个问题。例如,如果应用程序需要乐观并发,则需要在实体中添加@Version字段,并通过web服务自动公开此信息


通常,您希望控制公开的数据,并且通常希望解耦RESTAPI的DB实现。顺便说一句,通常您还需要一个域对象,其中包含用于验证的业务逻辑、业务规则……

IMO DTO方法是正确的。通常情况下,并不是所有的属性和形式都从JPA传递到DTO。至于JPA->DTO和back的转换,存在几种基于反射的方法,但最终也证明,从长远来看,手动复制属性是最稳健的方法。请注意,也可以使用Hibernate查询直接填充DTO。不要使用Dozer,因为它非常旧、过时,并且大量使用反射(Micronaut尝试删除所有反射)。我建议改用Mapstruct()。它使用Micronaut这样的注释处理器。Mapstruct看起来非常整洁,我喜欢无反射方法。将其标记为概述对应用程序设计(持久层、验证层、业务逻辑层)和@Version(甚至没有想到这一点:D)的影响的公认答案。非常感谢。实际上,在web应用程序中处理乐观锁定的唯一方法是向客户端公开版本字段。