您的位置:首页 > 其它

(二)MyBatis源码解析之配置文件

2016-05-31 20:05 791 查看
上篇文章我们分析了properties、environmets、typeAliases三个标签,这篇文章我们来看一下typeHandlers标签。

其实不用typeHandlers标签完全不影响对mybatis的使用。但是mybatis内部却大量使用了typeHandlers标签。

当MyBatis将一个Java对象作为输入参数执行Insert语句操作时,它会创建一个PreparedStatment对象,并且使用setxxx(...)方式对占位符设置相应的参数值。

这里,xxx可以使Int,String,Double等Java对象属性类型的任意一个,示例如下:

<insert id="insertStudent" parameterType="Student">
 INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(#{studId},#{name},#{email},#{dob})
</insert>
为执行这个语句,MyBatis将采用以下一系列动作:

1.创建一个有占位符的PreparedStatement接口,如下:

PreparedStatement pstmt = connection.prepareStatement ("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(?,?,?,?)");
检查Student对象的属性studId的类型然后使用setXXX(...)方法去设置参数值,这里studId是integer类型,所以会使用setInt(...)方法

pstmt.setInt(1,student.getStudId());
类似地,对于name和email属性都是String类型,Mybatis使用setString(...)设置参数

pstmt.setString(2, student.getName());
pstmt.setString(3, student.getEmail());
但问题是Mybatis是怎么知道对于Integer类型属性使用setInt(...)和String类型属性使用setString(...)方法呢?Mybatis其实就是使用类型处理器typeHandler来决定怎么做的

那如果我们给了一个自定义的对象类型,来存储到数据库呢?示例如下:

假设表STUDENTS有一个PHONE字段,类型为VARCHAR(15),而JavaBean Student 有一个PhoneNumber类定义类型的phoneNumber类

package net.klq.bean;

public class PhoneNumber {
private String countryCode;
private String stateCode;
private String number;

public PhoneNumber(String countryCode, String stateCode, String number) {
super();
this.countryCode = countryCode;
this.stateCode = stateCode;
this.number = number;
}

public PhoneNumber(String string) {
if (string != null) {
String[] parts = string.split("-");
if (parts.length > 0)
this.countryCode = parts[0];
if (parts.length > 0)
this.stateCode = parts[1];
if (parts.length > 0)
this.number = parts[2];
}
}

public String getAsString() {
return countryCode + "-" + stateCode + "-" + number;
}
}
class Student{
private Integer id;
private String name;
private String email;
private PhoneNumber phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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 PhoneNumber getPhone() {
return phone;
}
public void setPhone(PhoneNumber phone) {
this.phone = phone;
}

}
<insert id="insertStudent" parameterType="Student">
insert into students(name,email,phone)
values(#{name},#{email},#{phone})
</insert>


这里,phone参数需要传递给#{phone};而phone对象时PhoneNuber类型。但是,Mybatis并不知道该怎么处理这个对象

为了让MyBatis知道该怎样处理这个自定义的Java对象类型,如PhoneNumber,我们可以创建一个自定义的类型处理器,如下所示:

Mybatis提供了抽象类BaseTypeHandler<T> ,我们可以继承此类创建自定义的类型处理器。

package net.klq.bean;

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;

public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{

@Override
public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, parameter.getAsString());
}

@Override
public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
return new PhoneNumber(rs.getString(columnName));
}

@Override
public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return new PhoneNumber(rs.getString(columnIndex));
}

@Override
public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return new PhoneNumber(cs.getString(columnIndex));
}

}
一旦我们实现了自定义的类型处理器,我们需要在总的配置文件中注册它

<typeHandlers>
<typeHandler handler="net.klq.typehandler.PhoneTypeHandler"/>
</typeHandlers>
注册PhoneTypeHandler后,Mybatis能够将Phone类型的对象储存到varchar类型的列上

============================================上面就是typehandler的使用方法=============================================

typeHandler的解析很简单,就是将类的全路径名和和handler属性中指定的类存储到typeHandlerRegistry中,typeHandlerRegistry同样是configuration中的一个属性,mybatis默认已经帮我们初始化了很多typeHandler,所以我们才可以向数据库中直接插入普通类型的还有Date类型的等等的数据,项目是创建typeHandlerRegistry对象时Mybatis为我们初始化的typeHandler

public TypeHandlerRegistry() {
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());

register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());

register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());

register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());

register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());

register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());

register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());

register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());

register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());

register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());

register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());

register(Object.class, UNKNOWN_TYPE_HANDLER);
register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);

register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());

register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

// mybatis-typehandlers-jsr310
try {
register("java.time.Instant", "org.apache.ibatis.type.InstantTypeHandler");
register("java.time.LocalDateTime", "org.apache.ibatis.type.LocalDateTimeTypeHandler");
register("java.time.LocalDate", "org.apache.ibatis.type.LocalDateTypeHandler");
register("java.time.LocalTime", "org.apache.ibatis.type.LocalTimeTypeHandler");
register("java.time.OffsetDateTime", "org.apache.ibatis.type.OffsetDateTimeTypeHandler");
register("java.time.OffsetTime", "org.apache.ibatis.type.OffsetTimeTypeHandler");
register("java.time.ZonedDateTime", "org.apache.ibatis.type.ZonedDateTimeTypeHandler");
} catch (ClassNotFoundException e) {
// no JSR-310 handlers
}

// issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());
}

参考文献:

Java Persistence with MyBatis3

下载链接

http://download.csdn.net/detail/u010031673/9462976
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis typeHandlers