使用spring jpa投影强制枚举序列化?

sqserrrh  于 2023-04-04  发布在  Spring
关注(0)|答案(2)|浏览(134)

假设我有下面的JPA实体,枚举字段ON/OFFMap到SQL枚举(“on”,“off”)。

@Entity
public class Process {
    @Id
    private Long Id;
    @Convert(converter = StatusConverter.class)
    private Status status;

    // getter/setter omitted
}

public enum Status {
    ON("on"),
    OFF("off");

    private final String status;

    Status(String status) {
        this.status = status;
    }

    // JSON (de)serialization
    @JsonCreator
    public static Status decode(String status) {
        return valueOf(status.toUpperCase());
    }

    @JsonValue
    public getStatus() {
        return status;
    }

    // DAO layer conversion
    public String toDatabaseColumn() {
        return this.name().toLowerCase();
    }
}

@Converter
public class StatusConverter implements AttributeConverter<Status, String> {
    @Override
    public String convertToDatabaseColumn(Status attribute) {
        return attribute.toDatabaseColumn();
    }

    @Override
    public Status convertToEntityAttribute(String dbData) {
        return Status.decode(dbData);
    }
}

// Spring JPA projection
public interface ProcessSummary {
    String getStatus();
}

// a minimalist JPA repository
public interface ProcessRepository extends Repository<Process, Long> {
    <T> T findById(Long id, Class<T> type;
}

如果我在REST控制器中使用repository.findById(1L, Process.class),DAO层转换和JSON序列化都能按预期工作:

  • 我的数据库记录的状态设置为on
  • Map到Java Status.ON
  • 实体被序列化为
{
        "status" : "on" 
    }

但是如果我使用repository.findById(1L, ProcessSummary.class),则实体将序列化为

{
        "status" : "ON" 
    }

当使用投影作为目标类型时,我如何得到相同的结果?使用投影是否可能,或者我应该尝试其他方法(可能是DTO类)?

kr98yfug

kr98yfug1#

对不起,伙计们,这只是我和一个教科书案例的PEBKAC:)
接口中的getStatus()方法MUST返回Status,而不是String。

public interface ProcessSummary {
    String getStatus();
}

做它被要求做的事:将枚举转换为String,因此Status.ON被序列化为"ON",而

public interface ProcessSummary {
    Status getStatus();
}

实际上使用了@JsonValue注解的方法,并将Status.ON序列化为"on"

o2rvlv0m

o2rvlv0m2#

根据您的问题,您可以尝试使用enums-spring-boot-starter框架在两种情况下一致地处理enum序列化。此框架专为Java enum设计,可以自动处理数据库操作和API参数交换中的enum转换。
要使用此框架,请首先将以下依赖项添加到项目中:
玛文:

Copy code
<dependency>
    <groupId>io.gitee.zhucan123</groupId>
    <artifactId>enums-spring-boot-starter</artifactId>
    <version>1.1.8-RELEASE</version>
</dependency>

等级:

Copy code
implementation 'io.gitee.zhucan123:enums-spring-boot-starter:1.1.8-RELEASE'

接下来,修改Status枚举类以实现ExtensionEnum接口并添加@EnumAutoConverter注解:

Copy code
import com.example.enumspringbootstarter.autoconfig.annotation.EnumAutoConverter;
import com.example.enumspringbootstarter.autoconfig.interfaces.ExtensionEnum;

@Getter
@AllArgsConstructor
@EnumAutoConverter
public enum Status implements ExtensionEnum {
    ON("on"),
    OFF("off");

    private final String status;

    @Override
    public int getCode() {
        return this.ordinal();
    }

    @Override
    public String getDisplayName() {
        return this.status;
    }
}

现在可以删除StatusConverter类,因为enums-spring-boot-starter框架将为您处理转换。
在Process实体中,将@Convert注解更改为@Enumerated(EnumType.STRING):

Copy code
@Entity
public class Process {
    @Id
    private Long Id;

    @Enumerated(EnumType.STRING)
    private Status status;

    // getter/setter omitted
}

enums-spring-boot-starter框架将为Process和ProcessSummary一致地处理枚举序列化。当返回JSON响应时,它将自动使用您在Status枚举中定义的自定义字符串表示。
有关enums-spring-boot-starter框架的更多信息,请查看Gitee上的项目:https://gitee.com/your-gitee-username/enums-spring-boot-starter
我希望这对你有帮助!如果你有任何问题,请随时提出。

相关问题