了解mybatis的朋友都知道,当mybatis将一个java对象作为输入参数执行SQL语句时,会先创建一个PreparedStatement对象,通过该对象的setXxx()方法,将SQL语句中占位符替换,如下XxxMapper.xml配置文件:
insert into
students(id,name,email,date)
values(#{id},#{name},#{email},#{date})
mybatis在执行该sql语句时的步骤为:
1. 创建能够代替占位符的PreparedStatement接口
PreparedStatement ps = conn.prepareStatement("insert into students(id,name,email,date) values(?,?,?,?)");
2. 使用PreparedStatement的setXxx()方法进行替换
ps.setInt(1,student.getId()); ps.setString(2,student.getName()); ps.setString(3,student.getEmail()); ps.setTimestamp(4,new Timestamp((student.getDate()).getTime()));
这里就有一个疑问了,mybatis是如何知道什么时候应该使用setInt(),什么时候使用setString()的呢?就是通过类型处理器typeHandlers。
我们知道PreparedStatement的setXXX()方法支持的数据类型有限,一般常用的数据类型,mybatis会使用内置的类型处理器来进行处理,而当我们遇到的数据类型超出了这个范围,应该怎么做呢?
typeHandlers一般分为内置的和自定义。内置的类型处理器,上文已经提到了。自定义的类型处理器,顾名思义就是自己定义类型处理器,接下来我会举一个栗子。
public class Student {
private Integer id;
private String name;
private String email;
private PhoneNumber phone;
get()/set()...
}
在该Student类中出现了一个新的java类对象PhoneNumber
public class PhoneNumber {
private String countryCode;
private String stateCode;
private String number;
public PhoneNumber() {
}
public PhoneNumber(String countryCode, String stateCode, String number) {
this.countryCode = countryCode;
this.stateCode = stateCode;
this.number = number;
}
public String getAsString(){ return countryCode + "-" + stateCode + "-" + number;}
}
xml配置如下:
insert into students(name,email,phone)
values(#{name},#{email},#{phone})
在这里我们需要将值传给#{phone},而该占位符类型为PhoneNumber,内置的类型处理器处理不了这种类型,我们需要自定义类型处理器。mybatis提供了抽象类BaseTypeHandler
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.briup.pojo.PhoneNumber;
public class PhoneTypeHandler extends BaseTypeHandler {
//使用列名进行封装
@Override
public PhoneNumber getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return new PhoneNumber(rs.getString(columnName));
}
//使用列的下标进行封装
@Override
public PhoneNumber getNullableResult(ResultSet rs, int i)
throws SQLException {
return new PhoneNumber(rs.getString(i));
}
//CallableStatement遇到PhoneNumber,如何设置参数
@Override
public PhoneNumber getNullableResult(CallableStatement cs, int i)
throws SQLException {
return null;
}
//PreparedStatement遇到PhoneNumber,如何设置参数
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
PhoneNumber phoneNumber, JdbcType type) throws SQLException {
ps.setString(i, phoneNumber.getAsString());
}
}
我们还需要修改配置文件mybatis-config.xml文件来注册该类型处理器,在根标签下加入以下内容:
此时的类型处理器主要内容就是这么多。