Java 在测试代码中没有自动生成的字段时,如何序列化Hibernate实体?

Java 在测试代码中没有自动生成的字段时,如何序列化Hibernate实体?,java,spring,hibernate,jackson,Java,Spring,Hibernate,Jackson,我有一个具有以下字段的Hibernate实体: @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "first_name") private String firstName; @Column(name = "last_name

我有一个具有以下字段的Hibernate实体:

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;
}
我有一个端点来创建我想要测试的员工。为此,我需要发送实体的json表示,但不带数据库生成的id

我宁愿使用
ObjectMapper
来创建这些表示,而不是自己摆弄字符串

问题是
ObjectMapper.writeValueAsString(employee)
将在json中包含id
@JsonIgnore
无法使用,因为我需要服务器的响应来包含id

我看到的唯一解决方法是创建测试代码使用的自定义雇员序列化程序,例如:

public class EmployeeClientSerializer extends StdSerializer<Employee> {
    public EmployeeClientSerializer() {
        this(null);
    }

    public EmployeeClientSerializer(Class<Employee> e) {
        super(e);
    }

    @Override
    public void serialize(Employee employee, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("firstName", employee.getFirstName());
        gen.writeStringField("lastName", employee.getLastName());
        gen.writeStringField("email", employee.getEmail());
        gen.writeEndObject();
    }
}
公共类EmployeeClientSerializer扩展了StdSerializer{
公共EmployeeClientSerializer(){
这个(空);
}
公共EmployeeClientSerializer(e类){
超级(e);
}
@凌驾
public void serialize(Employee-Employee、JsonGenerator-gen、SerializerProvider-provider)引发IOException{
gen.writeStartObject();
gen.writeStringField(“firstName”,employee.getFirstName());
gen.writeStringField(“lastName”,employee.getLastName());
gen.writeStringField(“email”,employee.getEmail());
writeEndObject将军();
}
}

有更好的方法吗?

您可以创建一个DTO对象,它将表示不带ID字段的所需实体类实例。然后,您可以创建一个映射器来自动处理DTO实例构建过程(使用Mapstruct)。然后,您可以使用
ObjectMapper
实例序列化DTO实例。

通常,当事情变得复杂时,DTO类确实是最好的选择,但这也涉及从实体到DTO的映射,反之亦然

我不确定您打算如何序列化测试数据。但是,如果您唯一的问题是
id
中会有值,那么这应该不是问题,而且定制序列化程序可能是一个有点过分的解决方案。看看这个简化的类:

@Getter @Setter
public class PrimitiveId {
    private long id;        
    private String firstName;
} 
由于
id
属于primitive类型
long
,因此它不能为
null
,并默认为0。因此:

PrimitiveId primitiveId = new PrimitiveId();
primitiveId.setFirstName("Primitive");
System.out.println(om.writeValueAsString(primitiveId));
将打印:

{“id”:0,“firstName”:“Primitive”}

除了进行一些自定义序列化之外,您没有多少方法可以做到这一点。除非将
id
更改为boxed
Long
,如下所示:

@Getter @Setter
public class BoxedId {
    private Long id;
    private String firstName; 
}
连载

BoxedId boxedId = new BoxedId();
boxedId.setFirstName("Boxed");
System.out.println(om.writeValueAsString(boxedId));
现在就能生产了

{“id”:null,“firstName”:“Boxed”}

id
中的
null
不会造成伤害,因为它不会被序列化,毕竟它是
null

如果您真的需要摆脱它,请告诉
ObjectMapper

om.setSerializationInclusion(Include.NON_NULL); // serializes only non null values
System.out.println(om.writeValueAsString(boxedId));
{“firstName”:“Boxed”}


是的,没有想到DTO,因为请求和响应json基本相同。但这将是一个更干净的解决方案。现在,由于它是我唯一不想要的id,我将继续使用
Long
,并期待将来创建DTO。干杯