先来看代码:
(mybatis-3.4.5.jar)
/**
* Copyright 2009-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.property;
import java.util.Locale;
import org.apache.ibatis.reflection.ReflectionException;
/**
* @author Clinton Begin
*/
public final class PropertyNamer {
private PropertyNamer() {
// Prevent Instantiation of Static Class
}
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;
}
public static boolean isProperty(String name) {
return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
}
public static boolean isGetter(String name) {
return name.startsWith("get") || name.startsWith("is");
}
public static boolean isSetter(String name) {
return name.startsWith("set");
}
}
PropertyNamer.methodToProperty(String name)对应的便是setter-getter方法名到属性名的对应转换。
细读methodToProperty代码可知:
- 对于is开头的方法(通过针对boolean类型),直接取is后面的部分;
- 对于set/get开头的方法,直接substring(3),即取set/get后面的部分;
- 如果name长度等于1或者(长度大于1且第二个字母是小写的),将第一个字母转换为小写并拼接后面的部分作为属性名;
- 其他情况直接返回substring(2)-针对is开头或substring(3)-针对set/get开头;
下面看一个UserInfo类的定义:
package com.example.demo.utils;
import lombok.Data;
@Data
public class UserInfo {
private String name;
private String email;
private Integer uType;
}
可以看到,这里用到了lombok的@Data注解,它生成的uTyper的setter/getter方法长这样:

没错,这就是我们常看到的样子,预期似乎也应该长这样:set/get+第一个字母转换为大写。
这里的重点便是uType这个属性!!!
再通过PropertyNamer.methodToProperty方法的实现可以发现:
getUType/setUType这两个方法返回的属性名是:UType(因为第2个字母大写了~~~)
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {// 长度大于1且第二个字母小写的情况下进行拼接
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
这,就是我们用MyBatis写数据库时,明明通过debug发现属性是有值的,但写入数据库时某些字段却总是null的原因:属性名的第一个字母大写+使用了lombok生成的setter/getter方法,导致对应的属性名获取不到!!!
不过解决方法也简单:
1、修改属性名称,第2个字母改为小写,或者要求所有属性的前两个字母必需小写;
2、针对这种特殊的属性,使用idea自带的功能生成setter、getter方法

生成的代码如下:
package com.example.demo.utils;
import lombok.Data;
@Data
public class UserInfo {
private String name;
private String email;
private Integer uType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getuType() {
return uType;
}
public void setuType(Integer uType) {
this.uType = uType;
}
}
这里明显可以看到setuType/getuType和lombok生成的是不一样的(setUType/getUType)。
已踩坑~~~
记录+分享一下:)
MyBatis属性名映射陷阱解析

365

被折叠的 条评论
为什么被折叠?



