(二)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对象属性类型的任意一个,示例如下:
1.创建一个有占位符的PreparedStatement接口,如下:
那如果我们给了一个自定义的对象类型,来存储到数据库呢?示例如下:
假设表STUDENTS有一个PHONE字段,类型为VARCHAR(15),而JavaBean Student 有一个PhoneNumber类定义类型的phoneNumber类
这里,phone参数需要传递给#{phone};而phone对象时PhoneNuber类型。但是,Mybatis并不知道该怎么处理这个对象
为了让MyBatis知道该怎样处理这个自定义的Java对象类型,如PhoneNumber,我们可以创建一个自定义的类型处理器,如下所示:
Mybatis提供了抽象类BaseTypeHandler<T> ,我们可以继承此类创建自定义的类型处理器。
============================================上面就是typehandler的使用方法=============================================
typeHandler的解析很简单,就是将类的全路径名和和handler属性中指定的类存储到typeHandlerRegistry中,typeHandlerRegistry同样是configuration中的一个属性,mybatis默认已经帮我们初始化了很多typeHandler,所以我们才可以向数据库中直接插入普通类型的还有Date类型的等等的数据,项目是创建typeHandlerRegistry对象时Mybatis为我们初始化的typeHandler
参考文献:
Java Persistence with MyBatis3
下载链接
http://download.csdn.net/detail/u010031673/9462976
其实不用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传递多个参数的解决办法(三种)
- 深入浅析mybatis oracle BLOB类型字段保存与读取
- MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法
- SpringMVC整合mybatis实例代码
- oracle+mybatis 使用动态Sql当插入字段不确定的情况下实现批量insert
- MyBatis学习笔记(二)之关联关系
- 浅析Mybatis 在CS程序中的应用
- Java Mybatis框架入门基础教程
- Windows下Java+MyBatis框架+MySQL的开发环境搭建教程
- Mybatis与Ibatis的区别
- MyBatis学习教程(二)―如何使用MyBatis对users表执行CRUD操作
- MyBatis学习教程(四)-如何快速解决字段名与实体类属性名不相同的冲突问题
- Java简单实现SpringMVC+MyBatis分页插件
- MyBatis批量添加、修改和删除
- MyBatis与Hibernate的比较
- 浅析mybatis和spring整合的实现过程
- 在Java的MyBatis框架中建立接口进行CRUD操作的方法
- 整理Java的MyBatis框架中一些重要的功能及基本使用示例
- mybatis的动态sql详解(精)
- MyBatis实践之动态SQL及关联查询