我正在嘗試使用反射更新我的 DTO。
問題是我的 DTO 中的某些欄位是列舉,我收到一個錯誤,我無法將列舉欄位設定為String。
DTO:
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Table(name = "xxx")
public class Model {
@Id
@Column(name = "id")
private String runId;
@Column(name = "name")
private String name;
@Column(name = "status")
@Enumerated(EnumType.STRING)
private ExecutionStatus status;
}
控制器:
@PatchMapping(path = "/{id}", consumes = "application/json")
public ResponseEntity<Void> partialUpdateModel(@PathVariable String id, @RequestBody Map<Object, Object> fields)
throws Exception {
Optional<Model> model= service.getById(id);
if (model.isPresent()) {
fields.forEach((key, value) -> {
Field field = ReflectionUtils.findField(Model.class, (String) key);
field.setAccessible(true);
ReflectionUtils.setField(field, model.get(), value);
});
所以說到列舉欄位,欄位是不能設定的。它說
無法將 ExecutionStatus 設定為 String
uj5u.com熱心網友回復:
你想要做的是:
model.status = "STATUS_1";
// incompatible types: java.lang.String cannot be converted to so.A.ExecutionStatus
您顯然想要做的是找到具有指定字串的指定列舉型別的列舉常量。這就是Enum.valueOf或YourEnum.valueOf方法正在做的事情。
例子:
enum ExecutionStatus {
STATUS_1,
STATUS_2,
}
static class Model {
public String runId;
public String name;
public ExecutionStatus status;
@Override
public String toString() {
return "Model{"
"runId='" runId '\''
", name='" name '\''
", status=" status
'}';
}
}
public static void main(String[] args) {
Map<Object, Object> fields = Map.of(
"runId", "MyRunId",
"name", "MyName",
"status", "STATUS_1"
);
Model model = new Model();
fields.forEach((key, value) -> {
Field field = null;
try {
field = Model.class.getDeclaredField((String) key);
field.setAccessible(true);
if (field.getType().isEnum()) {
// First variant (YourEnum.valueOf(String)
Method valueOf = field.getType().getMethod("valueOf", String.class);
Object enumConstant = valueOf.invoke(null, value);
field.set(model, enumConstant);
// Alternative (Enum.valueOf(Class, String) (cast is safe due to isEnum)
field.set(model, Enum.valueOf((Class<Enum>) field.getType(), (String) value));
} else {
field.set(model, value);
}
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
});
System.out.println(model);
}
uj5u.com熱心網友回復:
你可以這樣做,還要理解反射是昂貴的,它涉及動態決議的型別,我建議改為撰寫 setter 或建構式
if ("ExecutionStatus".equalsIgnoreCase(field.getType().getSimpleName())) {
ReflectionUtils.setField(field, model.get(), ExecutionStatus.valueOf(value));
} else {
ReflectionUtils.setField(field, model.get(), value);
}
uj5u.com熱心網友回復:
這是因為您的源地圖是型別<Object, Object>
您嘗試做的是設定一個ExecutionStatus讀取型別值的型別欄位Object。您欄位上的型別必須匹配。首先轉換一個值,ExecutionStatus然后使用方法.setField(..)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/452761.html
上一篇:IllegalArgumentException:請求的結果型別不匹配-但型別已設定
下一篇:如何將我的頁面與控制器連接
