现在WEB开发经常使用 Mybatis 作为持久化框架,在开发过程中,会在Java代码中构建实体类与数据库表字段相互映射,
下面提出一个关于映射实体优化的方案:通过链式编程实现给实例对象赋值。
参考代码:
public class UserEntity{
private int userId;
private String userName;
private long lastLogin;
public int getUserId() {
return userId;
}
public UserEntity setUserId(int userId) {
this.userId = userId;
return this;
}
public String getUserName() {
return userName;
}
public UserEntity setUserName(String userName) {
this.userName = userName;
return this;
}
public long getLastLogin() {
return lastLogin;
}
public UserEntity setLastLogin(long lastLogin) {
this.lastLogin = lastLogin;
return this;
}
}
通过返回 this ,实现链式编程,但是返回 this 以后,Mybatis持久化框架给属性赋值的时候会不会出现问题,为了确认这个问题,查看了Mybatis的源码
Mybaits是通过反射给实体对象赋值的,在主要是调用的 Invoker 接口的相关实现类。
Invoker 接口定义:
public interface Invoker {
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
Class<?> getType();
}
在Mybatis中,通过Invoker的实现类 SetFieldInvoker 给实体赋值,通过 GetFieldInvoker 获取实体的值。
SetFieldInvoker 类定义:
public class SetFieldInvoker implements Invoker {
private Field field;
public SetFieldInvoker(Field field) {
this.field = field;
}
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
field.set(target, args[0]);
return null;
}
public Class<?> getType() {
return field.getType();
}
}
GetFieldInvoker 类定义:
public class GetFieldInvoker implements Invoker {
private Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return field.get(target);
}
public Class<?> getType() {
return field.getType();
}
}
二、Mybatis 异常情况
mapper.xml 定义:
<mapper namespace="xxx.xxx.xxx.UserMapper">
<sql id="user_field">
user_id,username,last_login
</sql>
<resultMap id="user" type="xxx.xxx.xxx.User">
<id property="userId" column="user_id"/>
<result property="userName" column="username"/>
<result property="" column="last_login"/>
</resultMap>
<update id="updateLastLogin" parameterType="xxx.xxx.xxx.User">
UPDATE user SET last_login = #{last_login} WHERE user_id = #{user_id}
</update>
</mapper>
当调用updateUser方法的时候,程序报错:There is no getter for property named ''last_login" in 'class xxx.xxx.xxx.User'
报这个错的原因是因为我们在#{} 里面应该填写User的属性,而不是列名,我们将 Update语句改为以下形式就正确了:
<update id="updateLastLogin" parameterType="xxx.xxx.xxx.User">
UPDATE user SET lastLogin = #{last_login} WHERE user_id = #{userId}
</update>