Mybatis类型转换
1.1 目录
1.2 建立TypeHandler
我们知道java有java的数据类型,数据库有数据库的数据类型,那么我们在往数据库中插入数据的时候是如何把java类型当做数据库类型插入数据库,在从数据库读取数据的时候又是如何把数据库类型当做java类型来处理呢?这中间必然要经过一个类型转换。在Mybatis中我们可以定义一个叫做TypeHandler类型处理器的东西,通过它可以实现Java类型跟数据库类型的相互转换。下面将就如何建立自己的TypeHandler做一个简要介绍。
1.2.1 TypeHandler接口
在Mybatis中要实现自己的TypeHandler就需要实现Mybatis为我们提供的TypeHandler接口。在TypeHandler中定义了四个方法:
- public interface TypeHandler<T> {
- /**
- * 用于定义在Mybatis设置参数时该如何把Java类型的参数转换为对应的数据库类型
- * @param ps 当前的PreparedStatement对象
- * @param i 当前参数的位置
- * @param parameter 当前参数的Java对象
- * @param jdbcType 当前参数的数据库类型
- * @throws SQLException
- */
- void setParameter(PreparedStatement ps, int i, T parameter,
- JdbcType jdbcType) throws SQLException;
- /**
- * 用于在Mybatis获取数据结果集时如何把数据库类型转换为对应的Java类型
- * @param rs 当前的结果集
- * @param columnName 当前的字段名称
- * @return 转换后的Java对象
- * @throws SQLException
- */
- T getResult(ResultSet rs, String columnName) throws SQLException;
- /**
- * 用于在Mybatis通过字段位置获取字段数据时把数据库类型转换为对应的Java类型
- * @param rs 当前的结果集
- * @param columnIndex 当前字段的位置
- * @return 转换后的Java对象
- * @throws SQLException
- */
- T getResult(ResultSet rs, int columnIndex) throws SQLException;
- /**
- * 用于Mybatis在调用存储过程后把数据库类型的数据转换为对应的Java类型
- * @param cs 当前的CallableStatement执行后的CallableStatement
- * @param columnIndex 当前输出参数的位置
- * @return
- * @throws SQLException
- */
- T getResult(CallableStatement cs, int columnIndex) throws SQLException;
- }
现在假设我们有一个实体对象User,其中有一个属性interests是String数组类型,如下所示:
- public class User {
- private int id;
- private String name;
- private int age;
- private String[] interests;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String[] getInterests() {
- return interests;
- }
- public void setInterests(String[] interests) {
- this.interests = interests;
- }
- @Override
- public String toString() {
- return "User [age=" + age + ", id=" + id + ", interests="
- + Arrays.toString(interests) + ", name=" + name + "]";
- }
- }
我们需要把它以拼接字符串的形式存到数据库中,然后在取出来的时候又把它还原为一个String数组。这个时候我们就可以给它定义一个TypeHandler专门来处理String数组类型和数据库VARCHAR类型的相互转换。在这里我们建立一个名叫StringArrayTypeHandler的TypeHandler,代码如下所示:
- package com.tiantian.mybatis.handler;
- import java.sql.CallableStatement;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Types;
- import org.apache.ibatis.type.JdbcType;
- import org.apache.ibatis.type.TypeHandler;
- public class StringArrayTypeHandler implements TypeHandler<String[]> {
- public String[] getResult(ResultSet rs, String columnName)
- throws SQLException {
- String columnValue = rs.getString(columnName);
- return this.getStringArray(columnValue);
- }
- public String[] getResult(ResultSet rs, int columnIndex)
- throws SQLException {
- String columnValue = rs.getString(columnIndex);
- return this.getStringArray(columnValue);
- }
- public String[] getResult(CallableStatement cs, int columnIndex)
- throws SQLException {
- // TODO Auto-generated method stub
- String columnValue = cs.getString(columnIndex);
- return this.getStringArray(columnValue);
- }
- public void setParameter(PreparedStatement ps, int i, String[] parameter,
- JdbcType jdbcType) throws SQLException {
- if (parameter == null)
- ps.setNull(i, Types.VARCHAR);
- else {
- StringBuffer result = new StringBuffer();
- for (String value : parameter)
- result.append(value).append(",");
- result.deleteCharAt(result.length()-1);
- ps.setString(i, result.toString());
- }
- }
- private String[] getStringArray(String columnValue) {
- if (columnValue == null)
- return null;
- return columnValue.split(",");
- }
- }
1.2.2 BaseTypeHandler抽象类
在实现自己的TypeHandler时,除了上面提到的实现最原始的接口之外,Mybatis还为我们提供了一个实现了TypeHandler接口的抽象类BaseTypeHandler。所以我们也可以通过继承BaseTypeHandler来实现自己的TypeHandler。
我们先来看一下BaseTypeHandler类的定义:
- public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
- protected Configuration configuration;
- public void setConfiguration(Configuration c) {
- this.configuration = c;
- }
- public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
- if (parameter == null) {
- if (jdbcType == null) {
- throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
- }
- try {
- ps.setNull(i, jdbcType.TYPE_CODE);
- } catch (SQLException e) {
- throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
- "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
- "Cause: " + e, e);
- }
- } else {