这里写自ibatis中使用typeHandler保存java对象到数据库字段定义目录标题

  • 提出问题
  • 解决方式一
  • 解决方式二
  • 解决方法三
  • 至此,可以优雅的解决java对象直接保存在数据库中的需求。


提出问题

有些时候,我们需要保存到数据库中的对象实体的属性也是个对象(包括自定义对象或者java库中提供的一
些对象)。但是数据库字段中目前支持的类型不包括自定义的对象和java库提供的某些对象。

解决方式一

大部分情况下,我们会将数据定义为String类型,赋值的时候将对象用JSON转换为String保存,这种方式有一些缺陷。第一是别人用到的时候需要对象和String相互转换,增加了额外的处理逻辑。第二是接口展示的时候会展示成String,数据多的时候看起来不是很直观。

解决方式二

为实体中的每个对象属性多定义一个String的属性,在getter和setter方法中处理两种数据,这样就可以做到set到实体中的属性是对象,但是保存在数据库中的是String,其实是在实体的getter和setter方法中做了一层转换。但是这种方式也有缺陷,因为这样相当于实体中的每个对象属性都多了一个备用的属性。提供给别人使用的时候很容易造成误解,并且接口展示的时候也会有很多无用字段造成困惑。如下面例子为xxx属性增加了一个备用的xxxTmp属性进行了转换,在sqlmap中配置xxxTmp属性即可。

public List<Xxx> getXxx() {
        return JSON.parseObject(this.getXxxTmp(),List.class);
    }
  
    public void setXxx(List<XXX>xxx) {
       this.setXxxTmp(JSON.toJSONString(xxx));
    }

    public String getXxxTmp() {
        return xxxTmp;
    }

    public void setXxxTmp(String xxxTmp) {
        this.xxxTmp = xxxTmp;
    }

解决方法三

使用ibatis提供的typeHandler方法来处理对象,其实ibatis已经为大部分的数据库支持字段进行了处理,比

如:

java中怎样将对象放入集合 java 把对象存到数据库_JSON

1、用户需要为自定义的对象定义对应的Handler 实现typeHandler接口就可以了,比如:

public class ComplexTypeHandler extends BaseTypeHandler implements TypeHandler,TypeHandlerCallback {


    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Object o, String s) throws SQLException {
        if(o!=null) {
            preparedStatement.setString(i, JSON.toJSONString(o));
        } else {
            preparedStatement.setString(i, null);
        }
    }

    @Override
    public Object getResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        return resultSet.wasNull()||StringUtil.isBlank(result) ?
                null : JSON.parseObject(result,List.class);
    }

    @Override
    public Object getResult(ResultSet resultSet, int i) throws SQLException {
        String result = resultSet.getString(i);
        return resultSet.wasNull()||StringUtil.isBlank(result) ? null : JSON.parseObject(result,List.class);
    }

    @Override
    public Object getResult(CallableStatement callableStatement, int i) throws SQLException {
        String result = callableStatement.getString(i);
        return callableStatement.wasNull()||StringUtil.isBlank(result) ? null : JSON.parseObject(result,List.class);
    }

    @Override
    public void setParameter(ParameterSetter parameterSetter, Object o) throws SQLException {

        if (null != o) {
            parameterSetter.setString(JSON.toJSONString(o));
        } else {
            parameterSetter.setString(null);
        }
    }

    @Override
    public Object getResult(ResultGetter resultGetter) throws SQLException {
        Object object = resultGetter.getObject();
        if (!resultGetter.wasNull()&&object!=null) {
            return StringUtil.isBlank(object.toString()) ? null : JSON.parseObject(object.toString(),List.class);
        } else {
            return null;
        }
    }

    @Override
    public Object valueOf(String s) {
        if(StringUtil.isBlank(s)){
            return null;
        }
        return JSON.parseObject(s,List.class);
    }

2、需要在sqlmap.xml 中需要进行配置,对于查询接口封装,配置如下:

<typeAlias alias="complexTypeHandler" type="com.xxx.xxxx.xxxx.ComplexTypeHandler"/>
 <resultMap id="xxxxxMap" class="xxxxxx">
        <result property="xxxxx" column="XXXXX" typeHandler="complexTypeHandler"/>
 </resultMap>

3、对于数据库插入和编辑的配置:

INSERT INTO `表名`(
        ,`字段名`
        )VALUES(
            #属性名,handler=com.xxx.xxxx.ComplexTypeHandler#
        );

UPDATE `表明` SET `GMT_MODIFIED` = now()        ]]>
        <dynamic>
            <isNotEmpty property="属性名" prepend=" , ">
                `字段名` = #属性名,handler=com.xxx.xxx.ComplexTypeHandler#
            </isNotEmpty>
        </dynamic>

4、在sqlMapConfig中声明

<typeHandler javaType="jave类型,比如自定义的class" callback="com.xxx.xxxx.xxxx.ComplexTypeHandler"/>

至此,可以优雅的解决java对象直接保存在数据库中的需求。