mybaits通过mapper文件进行数据库的增删改查操作,在进行增删改查操作时需要将java的数据类型与数据库的数据类型进行转换,此时就会用到TypeHandler类型处理器。mybatis内置了java基础数据类型的类型处理器,也支持自定义的类型处理器。
在博客系统开发时,对于博客文章的存储,我采用在oracle数据库中存储blob字段的形式,前端使用layui的富文本编辑器进行编辑和展示文章。前端传入需要保存的文章是一个string类型,怎样使用mybatis持久层保存到数据库的blob字段中呢,以及从数据库中查出blob字段并转换成java中的string类型以更好的返回给前端呢,此时就需要用到自定义的类型处理器。
1、自定义BlobTypeHandler类型处理:集成BaseTypeHandler类,实现抽象方法,在抽象方法中实现类型处理即可
/**
*
* @ClassName::BlobTypeHandler
* @Description: 自定义mybatis blob字段处理
* @author :柯雷
* @date :2018年9月28日 下午2:54:36
*
*/
public class BlobTypeHandler extends BaseTypeHandler<String> {
/**
* @Description 日志打印对象
*/
Logger logger = LoggerFactory.getLogger(BlobTypeHandler.class);
/**
* <p>Title:setNonNullParameter</p>
* <p>Description:insert或者update时前处理blob字段 </p>
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
* @see org.apache.ibatis.type.BaseTypeHandler#setNonNullParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType)
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
logger.info("【BlobTypeHandler】insert或者update时处理blob字段:");
//声明一个输入流对象
ByteArrayInputStream bis = null;
try {
//把字符串转为字节流
bis = new ByteArrayInputStream(parameter.getBytes("gbk"));
} catch (Exception e) {
logger.error("【BlobTypeHandler】insert或者update处理blob字段出错,错误原因为:" + e);
throw new RuntimeException("Blob Encoding Error!");
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
logger.error("【BlobTypeHandler】insert或者update处理blob字段出错,错误原因为:" + e);
throw new RuntimeException("Blob Encoding Error!");
}
}
}
ps.setBinaryStream(i, bis, Util.getDbLength(parameter));
}
/**
* <p>Title:getNullableResult</p>
* <p>Description: 查询成功后处理blob字段</p>
* @param rs
* @param columnName
* @return
* @throws SQLException
* @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String)
*/
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
logger.info("【BlobTypeHandler】query查询时处理blob字段");
Blob blob = (Blob) rs.getBlob(columnName);
byte[] returnValue = null;
if (null != blob) {
returnValue = blob.getBytes(1, (int) blob.length());
}
try {
//将取出的流对象转为utf-8的字符串对象
return new String(returnValue, "gbk");
} catch (Exception e) {
logger.error("【BlobTypeHandler】查询处理blob字段出错,错误原因为:" + e);
throw new RuntimeException("Blob Encoding Error!");
}
}
/**
* <p>Title:getNullableResult</p>
* <p>Description: 查询成功后处理blob字段 </p>
* @param rs
* @param columnIndex
* @return
* @throws SQLException
* @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, int)
*/
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
logger.info("【BlobTypeHandler】query查询时处理blob字段");
Blob blob = (Blob) rs.getBlob(columnIndex);
byte[] returnValue = null;
if (null != blob) {
returnValue = blob.getBytes(1, (int) blob.length());
}
try {
//将取出的流对象转为utf-8的字符串对象
return new String(returnValue, "gbk");
} catch (Exception e) {
logger.error("【BlobTypeHandler】查询处理blob字段出错,错误原因为:" + e);
throw new RuntimeException("Blob Encoding Error!");
}
}
/**
* <p>Title:getNullableResult</p>
* <p>Description: 查询成功后处理blob字段</p>
* @param cs
* @param columnIndex
* @return
* @throws SQLException
* @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.CallableStatement, int)
*/
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
logger.info("【BlobTypeHandler】query查询时处理blob字段");
Blob blob = (Blob) cs.getBlob(columnIndex);
byte[] returnValue = null;
if (null != blob) {
returnValue = blob.getBytes(1, (int) blob.length());
}
try {
//将取出的流对象转为utf-8的字符串对象
return new String(returnValue, "gbk");
} catch (Exception e) {
logger.error("【BlobTypeHandler】查询处理blob字段出错,错误原因为:" + e);
throw new RuntimeException("Blob Encoding Error!");
}
}
}
2、mapper文件中使用类型处理器:下图content字段处理
update,保存到数据库中
<!-- 更新文章信息 -->
<update id="updateArticle" parameterType="map">
UPDATE BLOG_ARTICLE
<set>
<if test="TITLE != null and TITLE != ''">TITLE = #{TITLE},</if>
<if test="ABSTRACT != null and ABSTRACT != ''">ABSTRACT = #{ABSTRACT},</if>
<if test="TYPEID != null and TYPEID != ''">TYPEID = #{TYPEID},</if>
<if test="TAGID != null and TAGID != ''">TAGID = #{TAGID},</if>
<if test="SOURCE != null and SOURCE != ''">SOURCE = #{SOURCE},</if>
<if test="PHOTO != null and PHOTO != ''">PHOTO = #{PHOTO},</if>
<if test="CONTENT != null and CONTENT != ''">CONTENT = #{CONTENT, typeHandler=cn.muchen.framework.dao.handler.BlobTypeHandler},</if>
<if test="SFFB != null and SFFB != ''">SFFB = #{SFFB},</if>
<if test="AUTHOR != null and AUTHOR != ''">AUTHOR = #{AUTHOR},</if>
<if test="PRAISECOUNT != null and PRAISECOUNT != ''">PRAISECOUNT = PRAISECOUNT + 1,</if>
<if test="TREADCOUNT != null and TREADCOUNT != ''">TREADCOUNT = TREADCOUNT + 1,</if>
<if test="CRITICCOUNT != null and CRITICCOUNT != ''">CRITICCOUNT = CRITICCOUNT + 1,</if>
<if test="READCOUNT != null and READCOUNT != ''">READCOUNT = READCOUNT + 1,</if>
<if test="VALIDATED != null and VALIDATED != ''">VALIDATED = #{VALIDATED},</if>
<if test="MEMO != null and MEMO != ''">MEMO = #{MEMO},</if>
<if test="BAE004 != null and BAE004 != ''">BAE003 = SYSDATE, BAE004 = #{BAE004},</if>
</set>
WHERE ARTICLEID = #{ARTICLEID}
</update>
select,从数据库中查询
<!-- 根据文章id查询文章信息 -->
<select id="getArticleById" parameterType="integer" resultMap="queryArticleMap">
SELECT <include refid="BLOG_ARTICLE_COLUMN"/> FROM BLOG_ARTICLE WHERE ARTICLEID = #{ARTICLEID}
</select>
<!-- 返回数据类型 -->
<resultMap id="queryArticleMap" type="map">
<result column="ARTICLEID" property="ARTICLEID" jdbcType="INTEGER" />
<result column="TITLE" property="TITLE" jdbcType="VARCHAR" />
<result column="ABSTRACT" property="ABSTRACT" jdbcType="VARCHAR" />
<result column="TYPEID" property="TYPEID" jdbcType="VARCHAR" />
<result column="TAGID" property="TAGID" jdbcType="VARCHAR" />
<result column="SOURCE" property="SOURCE" jdbcType="VARCHAR" />
<result column="PHOTO" property="PHOTO" jdbcType="VARCHAR" />
<result column="CONTENT" property="CONTENT" typeHandler="cn.muchen.framework.dao.handler.BlobTypeHandler" />
<result column="SFFB" property="SFFB" jdbcType="VARCHAR" />
<result column="AUTHOR" property="AUTHOR" jdbcType="VARCHAR" />
<result column="PARENTID" property="PARENTID" jdbcType="INTEGER" />
<result column="READCOUNT" property="READCOUNT" jdbcType="INTEGER" />
<result column="VALIDATED" property="VALIDATED" jdbcType="VARCHAR" />
<result column="MEMO" property="MEMO" jdbcType="VARCHAR" />
<result column="BAE001" property="BAE001" jdbcType="DATE" />
<result column="BAE002" property="BAE002" jdbcType="INTEGER" />
<result column="BAE003" property="BAE003" jdbcType="DATE" />
<result column="BAE004" property="BAE004" jdbcType="INTEGER" />
</resultMap>
经过上述配置,java代码中无需关心content字段在数据库中的存储类型,直接以string类型处理即可,因为每次在保存之前都会经过自定义的BlobTypeHandler类型处理器将java string类型处理为blob存入数据库,在查询之后会将从数据库查出的blob处理为string给到返回结果中。