- 浏览: 144265 次
- 性别:
- 来自: 上海
最新评论
-
shuanggui1990:
Spring及其优点 -
wujingyong:
zhuzf 写道 , 我的就是这个问题,解决了,3Q具体是怎 ...
MyBatis 物理分页foreach 参数失效 -
xuqiao2009:
高人高人,佩服void processIntercep ...
MyBatis 物理分页foreach 参数失效 -
atwind:
有.net的实现吗?
.NET和Java中BYTE的区别 -
zhuzf:
, 我的就是这个问题,解决了,3Q
MyBatis 物理分页foreach 参数失效
iBatis的扩展组件主要有TypeHandlerCallback、CacheController、 DataSourceFactory、TransactionConfig。其中TypeHandlerCallback可以实现自定义的类型处理逻辑, 以便处理非标准数据库、驱动程序和(或)数据类型。
场景举例
有如下数据表,请注意字段status的类型及含义:
- CREATE DATABASE ibatis;
- USE test_ibatis;
- CREATE TABLE person
- (
- id INT NOT NULL AUTO_INCREMENT,
- name VARCHAR (20) NOT NULL comment '姓名' ,
- status TINYINT NOT NULL comment '状态(1可用,-1不可用,0默认)' ,
- PRIMARY KEY (id)
- )
- ENGINE=InnoDB
- DEFAULT CHARACTER SET =utf8;
对应的实体模型类里将status定义为枚举型,如:
- public class Person {
- private int id;
- private String name;
- private Status status; // 注意这里
- // getters and setters...
- }
注:如果将status定义为整型,虽然与表中的字段类型一致了,但在赋值时setStatus(int status),只能传数字,不易被理解,没有人会明白应该传什么值,1或-1又代表了什么含义,且易产生脏数据,比如有意无意间会传321。
用枚举型给status赋值,既直观又限定范围。如:
- ......
- Person person = new Person();
- person.setName("yumin" );
- person.setStatus(Status.AVAILABLE);; // 注意这里
- boolean result = DAO.insert(person);
- .......
代码里出现的枚举型Status,可以这样进行定义:
但按上述做法执行写入操作时,发生了如下异常:
- Caused by: java.sql.SQLException:
- Incorrect integer value: 'AVAILABLE' for column 'status' at row 1
类型不匹配,AVAILABLE用在了整型字段status。
异常出现的症结在于, 数据表里的字段是用整型存储这没问题, 但Java代码里应该用枚举型会更友好, 两者间在数据类型上就存在一定的矛盾, 即"javaType=enum"而"jdbcType=integer" 。这时就需用到TypeHandlerCallback,通过实现该接口来处理中间的转换。
题外话:还有一种做法,定义Person类时,定义两个status,第一个status为整型,但取消setStatus方法,只负责在数据表存 储时用,另一个叫status2为枚举型,负责与外部交互,赋值时只能用status2,内部将status2转换为status,这样既能保证友好又能 通过转换保持类型的一致。但暂时让我们看看若通过iBatis的扩展应该如何实现。
实例演示
TypeHandlerCallback接口,下面是它的源代码:
- public abstract interface TypeHandlerCallback {
- public abstract void setParameter(ParameterSetter setter, Object object)
- throws SQLException;
- public abstract Object getResult(ResultGetter getter) throws SQLException;
- public abstract Object valueOf(String string);
- }
接下来我们一起Step-by-step操作 ——
第一步:基于TypeHandlerCallback实现类
- /**
- *
- */
- package me.yumin.java.ibatis.handler;
- import com.ibatis.sqlmap.client.extensions.ParameterSetter;
- import com.ibatis.sqlmap.client.extensions.ResultGetter;
- import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
- import java.sql.SQLException;
- import java.sql.Types;
- import me.yumin.java.ibatis.enumtype.Status;
- /**
- * @author yumin
- *
- */
- public class StatusHandler implements TypeHandlerCallback {
- @Override
- public void setParameter(ParameterSetter setter, Object parameter)
- throws SQLException {
- /*
- * 在sqlMap中配parameterMap的属性typeHandler
- * 和sqlMapConfig中配全局typeHandler时才会触发
- */
- if ( null == parameter) {
- setter.setNull(Types.INTEGER); // 若没有传值则null,表字段不允许则异常
- } else {
- setter.setInt(((Status) parameter).getValue());
- }
- }
- @Override
- public Object getResult(ResultGetter getter) throws SQLException {
- /*
- * 仅在sqlMap中配置resultMap的属性typeHandler
- * 和在sqlMapConfig中配全局typeHandler才会触发
- */
- Object result = null ;
- //if (!getter.wasNull() && null != getter.getObject()) {
- // 上面有问题,修复如下.wasNull是判断前一个字段是否为null
- if ( null != getter.getObject()) {
- result = getStatus(getter.getInt());
- }
- return result;
- }
- @Override
- public Object valueOf(String string) {
- /*
- * 处理属性或参数为null情况
- * 入参即为配置项nullValue
- */
- Object result = null ;
- int integer = 0 ;
- if ( null != string && 0 < string.length()) {
- try {
- integer = Integer.parseInt(string);
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- result = getStatus(integer);
- return result;
- }
- /**
- *
- * @param value
- * @return
- */
- private Object getStatus( int value) {
- Object result = null ;
- for (Status status : Status.values()) {
- if (value == status.getValue()) {
- result = status;
- break ;
- }
- }
- return result;
- }
- }
第二步:在sqlMap中指定属性typeHandler
所有完整的sqlMap配置文件如下:
- <? xml version = "1.0" encoding = "UTF-8" ?>
- <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
- < sqlMap namespace = "Person" >
- < typeAlias alias = "Person" type = "me.yumin.java.ibatis.domain.Person" />
- < parameterMap class = "Person" id = "person" >
- < parameter property = "name" />
- < parameter property = "status" typeHandler = "me.yumin.java.ibatis.handler.StatusHandler" />
- <!-- 若没有使用parameterMap且未给属性指定typeHandler
- 则在给SQL传值时不会调Handler中的setParameter方法 -->
- </ parameterMap >
- < resultMap class = "Person" id = "person" >
- < result property = "id" column = "id" />
- < result property = "name" column = "name" />
- < result property = "status" column = "status" typeHandler = "me.yumin.java.ibatis.handler.StatusHandler" nullValue = "0" />
- <!-- 同上若没用resultMap且未给属性指定typeHandler
- 则在返回表数据时不会调Handler中的getResult方法 -->
- </ resultMap >
- < insert id = "insert" parameterMap = "person" >
- <![CDATA[
- INSERT INTO person (name, status) VALUES (?, ?)
- ]]>
- < selectKey keyProperty = "id" resultClass = "java.lang.Integer" >
- SELECT LAST_INSERT_ID()
- </ selectKey >
- </ insert >
- < select id = "query" parameterClass = "java.lang.Integer" resultMap = "person" >
- <![CDATA[
- SELECT id, name, status FROM person WHERE id=#id#
- ]]>
- </ select >
- </ sqlMap >
主要处理过程是,因在sqlMap中给属性配置了typeHandler,所以在写或改数据前,先调用setParameter方法,再生成SQL,这时已将枚举型转换为整型;在读取数据后映射类时,会调用getResult方法,将整型转换为枚举型。
完整的示例请见附件,导入到IDE即可运行, IBatisTest是测试用例。
上述实例满足了一开始的需求,即Java类中将属性定义为枚举型,在存储时仍用整型,既友好直观地让使用者给类赋值又满足了存储需要。应用场景还有 很多,如:对所有字符串型数据先压缩再存储,则可在sqlMapConfig中定义全局typeHandler, 凡"javaType=java.lang.String"时,都通过该扩展在写之前先压缩,读取后先解压再返回。
若将Handler定义在sqlMapConfig,则该typeHandler是全局可用的。
全局typeHandler定义:
- < sqlMapConfig >
- ......
- < typeHandler javaType = "package.Type" callback = "package.Handler" />
- ......
- </ sqlMapConfig >
转自http://blog.csdn.net/solo_knight/article/details/7715683
发表评论
-
JQuery Tree插件——zTree
2013-03-11 13:36 821zTree -- jQuery 树插件 zTree ... -
Spring3.1 Cache注解
2013-03-07 10:37 840Spring3.1 Cache注解 博客分类: S ... -
Spring MVC学习之(转)
2013-02-22 14:44 889Spring MVC学习之一:基础入门 Spring M ... -
那些你该了解的Spring子项目
2013-01-24 10:28 827转自:http://www.infoq.com/cn/ne ... -
性能调优攻略
2013-01-23 22:16 736转自:http://coolshell.cn/article ... -
由12306.cn谈谈网站性能技术(转)
2013-01-23 22:15 847转自:http://coolshell.cn/artic ... -
MyBatis 物理分页foreach 参数失效
2013-01-17 11:47 6769场景:MyBatis 物理分页,查询条件中需要用到forea ... -
HTTP协议之状态码详解
2013-01-15 12:58 866转自:http://v5browser.iteye.com/ ... -
CXF jar包冲突之asm
2012-07-27 15:53 4976场景:一个web项目,用了SSH框架,在选择webservic ... -
spring设置动态定时任务
2012-06-28 22:48 922什么是动态定时任务:是由客户制定生成的,服务端只知道该去执行什 ... -
cronExpression配置说明
2012-06-28 21:58 731cronExpression配置说明 字段 允许值 ... -
Struts2 之convention-plugin实现零配置
2012-06-18 22:58 520Struts2使用Convention插件,你需要将其JAR文 ... -
jQuery 选择元素
2012-06-18 22:21 9011.$()函数 在jQuery中,$()函数充当一个工厂,可 ... -
jQuery 优点
2012-06-17 22:09 870JQuery是一个优秀的javascript框架,优点 1. ... -
Spring及其优点
2012-06-14 23:23 48385大部分项目都少不了Spring的身影,为什么大家对他如此青睐 ...
相关推荐
NULL 博文链接:https://wangym.iteye.com/blog/1439520
ibatis简易使用ibatis简易使用ibatis简易使用
ibatis学习 ibatis总结 ibatis ibatis ibatis
ibatis 相关使用文档及安装包ibatis 相关使用文档及安装包
12.2 使用自定义类型处理器 217 12.2.1 实现自定义类型处理器 217 12.2.2 创建TypeHandlerCallback 218 12.2.3 注册TypeHandlerCallback以供使用 221 12.3 使用CacheController 222 12.3.1 创建CacheController 223 ...
ibatis教程 主要是对这个软件的入门的介绍和如何加载和使用
使用ibatis和Oracle数据库实现的小项目,供初学者参考
在.net中使用iBATISNET技术!该例子使用vs2008开发。现在调整资源分为之前的一半,方便大家下载吧。
使用Ibatis对数据库的访问,实现增删改查的操作 ;
ibatis 使用手册:ibatis 开发指南、ibatis sql maps、ibatis sql maps 入门教程。
ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料ibatis资料
ibatis 读取oracle clob类型
ibatis中自己能运行的,还有能跟SSI整合的类库都在里面
ibatis demo,ibatis例子,ibatis示例
Ibatis3,手册,Ibatis3手册,Ibatis3使用手册,Ibatis3参考手册
iBATIS 级联iBATIS 级联iBATIS 级联
ibatis中输入输出各种类型的参数分析及#与$区别
Ibatis调用Oracle存储过程,返回自定义的类型。
ibatis的原码 ibatis源码 ibatis源码 ibatis源码
ibatis的例子,快速使用ibatis,直接就能用