Why Enum Status Vanishes on DB Insert: Debugging Java Enum Misuse with Arthas
A Java backend developer investigates why an enum‑based status field becomes an empty string during database insertion, tracing the issue through code inspection, Arthas watches, and ultimately discovering a mis‑implemented enum setter caused by a third‑party library.
Today a colleague reported a puzzling bug: after setting the status field of a PayRequest object (an enum) and inserting the corresponding PayRequestDO into the database, the stored status became an empty string. The code involved a simple service method that converts the request to a DO and calls MyBatis insert.
Problem Code
@Override
public String insert(PayRequest payRequest) {
// ...
PayRequestDO payRequestDO = convertor.toDO(payRequest);
payMapper.insert(payRequestDO);
return payRequest.getPayNo();
}The POJOs are straightforward:
public class PayRequest {
private String payId;
private String payNo;
private Status status;
// getters/setters
}
public class PayRequestDO {
private String payId;
private String payNo;
private String status;
// getters/setters
}The converter copies properties:
public PayRequestDO toDO(PayRequest payRequest) {
PayRequestDO payRequestDO = new PayRequestDO();
payRequestDO.setPayId(payRequest.getPayId());
payRequestDO.setPayNo(payRequest.getPayNo());
payRequestDO.setStatus(payRequest.getStatus().getCode());
return payRequestDO;
}Initial Checks
After confirming the deployed code matches the source, the team used MySQL digest logs, which showed the generated INSERT statement already contained '' for status, indicating the loss occurs before the ORM step.
Using Arthas to Trace Values
Arthas watch commands were applied to the service method, the mapper, and the converter. The watches revealed that status is present as Status.INIT when entering the service, but becomes an empty string after the toDO conversion.
Root Cause: Enum Setter Misuse
The Status enum is defined with mutable code and desc fields and provides a setCode method:
public enum Status {
INIT("INIT", "初始态"),
SUCCESS("SUCCESS", "成功"),
FAILED("FAILED", "失败");
private String code;
private String desc;
// constructor, getters, setters
public void setCode(String code) { this.code = code; }
}Because the fields are not final, a third‑party library (Podam) that generates random objects via reflection invoked the enum's setter, overwriting the original code with an empty value. This caused the converter to store an empty string.
Verification
Adding logging inside setCode (either by throwing an exception or printing the stack trace) confirmed that Podam was the culprit.
Remediation
Make enum fields final and remove setter methods to enforce immutability.
Configure static analysis tools (e.g., Sonar) to flag mutable enums.
Report the Podam bug and avoid using it for enum types, or upgrade to a fixed version.
Add a custom rule to the internal code‑scan platform to detect mutable enums.
By following these steps, the status field is correctly persisted, and similar issues can be prevented in future projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
