Why Lombok’s Getter/Setter Breaks MyBatis and EasyExcel – and How to Fix It
This article explains how Lombok’s unconventional getter/setter naming for fields with a lowercase‑first, uppercase‑second pattern causes MyBatis to map enum properties as null, and how the @Accessor(chain=true) annotation in EasyExcel triggers cglib reflection issues, then provides practical workarounds for both problems.
Recently, developers have encountered a recurring pitfall when using Lombok: the generated getter and setter methods for fields whose first letter is lowercase and second letter is uppercase (e.g., nMetaType) do not follow the naming conventions expected by MyBatis and other Java reflection utilities.
Problem with Lombok‑generated Getter/Setter
In a project that uses Lombok’s @Data annotation, an entity class similar to the following was defined:
@Data
public class NMetaVerify {
private NMetaType nMetaType;
private Long id;
// ... other fields
}When inserting this entity with MyBatis, all fields were persisted correctly except nMetaType, which remained NULL in the database.
Root Cause
Lombok generates the accessor methods as setNMetaType and getNMetaType (the second character is capitalized). MyBatis, however, derives property names from method names using the standard JavaBeans convention, which expects setnMetaType and getnMetaType for a field named nMetaType. Because the method names do not match, MyBatis cannot map the property, resulting in a NULL column value.
The official JavaBeans introspection logic (used by MyBatis) is illustrated in the source of PropertyNamer:
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}A test case prints the conversion results for several method names:
@Test
public void foundPropertyNamer() {
String isName = "isName";
String getName = "getName";
String getnMetaType = "getnMetaType";
String getNMetaType = "getNMetaType";
Stream.of(isName, getName, getnMetaType, getNMetaType)
.forEach(m -> System.out.println("Method: " + m + " Property: " + PropertyNamer.methodToProperty(m)));
}The output shows that getNMetaType is converted to NMetaType (incorrect), while getnMetaType yields the expected nMetaType.
Solutions for Lombok Issue
Rename the field so that the first two letters are both lowercase (e.g., nmMetaType), ensuring Lombok generates standard JavaBeans methods.
If the database schema and existing APIs cannot be changed, manually write the getter and setter for the problematic field (or let the IDE generate them) instead of relying on Lombok.
@Accessor(chain = true) Annotation Problem in EasyExcel
When exporting data with EasyExcel, newly added entity classes that include the Lombok annotation @Accessor(chain = true) fail to export correctly. The annotation is intended to enable fluent‑style setters (e.g., new UserDto().setUserName(...).setAge(...)).
Underlying Cause
EasyExcel uses Alibaba’s cglib library for reflection. Internally, cglib relies on the JDK’s Introspector class to discover property descriptors. The relevant snippet from Introspector shows that it only treats methods whose names start with get, set, or is and whose return type matches the expected pattern. Because the fluent setters generated by @Accessor(chain = true) return the object itself (i.e., a non‑void type), Introspector does not recognize them as valid setters, causing EasyExcel to miss those properties during export.
if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
} else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {
// Simple setter
pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
if (throwsException(method, PropertyVetoException.class)) {
pd.setConstrained(true);
}
}Solutions for @Accessor Issue
Remove the @Accessor(chain = true) annotation from the entity class, reverting to standard void‑returning setters.
Await a future EasyExcel release (or contribute a patch) that modifies the underlying reflection strategy to accept fluent setters whose return type is the bean itself.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
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.
