﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-kingmove-随笔分类-ibatis</title><link>http://www.blogjava.net/kingmove/category/39596.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 15 May 2009 09:25:47 GMT</lastBuildDate><pubDate>Fri, 15 May 2009 09:25:47 GMT</pubDate><ttl>60</ttl><item><title>引用网上另一篇文章[ibatis插入空值问题]</title><link>http://www.blogjava.net/kingmove/archive/2009/05/15/270888.html</link><dc:creator>KingMove</dc:creator><author>KingMove</author><pubDate>Fri, 15 May 2009 08:50:00 GMT</pubDate><guid>http://www.blogjava.net/kingmove/archive/2009/05/15/270888.html</guid><wfw:comment>http://www.blogjava.net/kingmove/comments/270888.html</wfw:comment><comments>http://www.blogjava.net/kingmove/archive/2009/05/15/270888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kingmove/comments/commentRss/270888.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kingmove/services/trackbacks/270888.html</trackback:ping><description><![CDATA[<h1 class="title_txt">Ibatis 关于空值(NULL)的解决方案</h1>
<div class="blogstory"><script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
<p>文章出自:http://blog.sina.com.cn/s/blog_520998920100b4d3.html</p>
<div class="articleContent" id="articleBody">
<p>使用Ibatis作为数据库持久层的人都有体会,Ibatis 对NULL值的处理并不优雅.本文讨论常见的NULL值处理方案.jdbcType 应该是<strong>java.sql.Types</strong> 中所列举的类型中的一种.</p>
<p><span style="color: rgb(255,0,0)">1.String为NULL的处理</span>:拿SQL Server 来说,其中与String对应的类型有很多种,如VARCHAR,NVARCHAR,TEXT...如果存入数据库中的值有可能为NULL的时候,我们只要在插入或者更新的时候指定它的类型为VARCHAR,或者LONGVARCHAR,对应TEXT类型<span style="color: rgb(255,0,0)">,(注意不能为NVARCHAR,和LONGNVARCHAR):</span>如下</p>
<p>&lt;update id="update"&gt;<br />
&nbsp; &nbsp;UPDATE [ArtT_user]<br />
&nbsp;&nbsp; SET [ArtT_sUserName] = #userName#<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,[ArtT_sUserPwd] = #password#<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255,0,0)">,[ArtT_sUserEmail] = #userEmail:VARCHAR#<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255,0,0)">,[ArtT_sUserDescription] = #description:LONGVARCHAR#<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHERE [ArtT_iUserId] = #userId#<br />
&nbsp; &lt;/update&gt;</p>
<p>如果属性userEmail,description为空时,Ibatis把NULL存入数据库.</p>
<p>数据库取出值为NULL,对应的属性为String类型的时候,无需作特别处理,Ibatis会把相应属性设置为空.</p>
<p><span style="color: rgb(255,0,0)">2.date ,datetime的处理:</span>与String的处理相类似,插入或者更新数据时,应该指定日期的类型,DATE 或者TIMESTAMP,如下:</p>
<p>&nbsp;&lt;update id="update"&gt;<br />
&nbsp; &nbsp;UPDATE [ArtT_user]<br />
&nbsp;&nbsp; SET [ArtT_sUserName] = #userName#<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,[ArtT_sUserPwd] = #password#<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255,0,0)">,[ArtT_dLastLoginTime] = #lastLoginTime:TIMESTAMP#<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(255,0,0)">,[ArtT_sCreateDate] = #createDate:DATE#<br />
</span>&nbsp;WHERE [ArtT_iUserId] = #userId#<br />
&nbsp; &lt;/update&gt;</p>
<p>同时,从数据库中取出值时,在resultMap中也应该指定明确的类型,DATE 或者DATETIME,如下:</p>
<p>&lt;result property="lastLoginTime"column="ArtT_dLastLoginTime" columnIndex="12"<span style="color: rgb(255,0,0)">jdbcType="TIMESTAMP"/</span>&gt;<br />
&lt;result property="createDate" column="ArtT_sCreateDate" columnIndex="13" <span style="color: rgb(255,0,0)">jdbcType="DATE"/</span>&gt;</p>
<p><span style="color: rgb(255,0,0)">3.int,double,float的处理</span>:根据Ibatis 官方文档介绍,因为在javaBean中如果属性为int ,double, float 时,不允许设置为NULL,可以采用一个"神奇数字"来代替属性中的NULL,如-9999.</p>
<p>数据存入数据库时,当检测到属性值为-9999时,Ibatis把空值存入数据库中.</p>
<p>数据从数据库中取出时,当数据库中该字段为NULL时,Ibatis给javaBean中的属性赋值为-9999.</p>
<p><span style="color: rgb(255,0,0)">因此,在XML映射文件中,应该<strong>同时</strong>在<strong>存入</strong>与<strong>取出</strong>处指定nullValue='-9999',否则容易导致数据库的不一致.</span></p>
<p><span style="color: rgb(0,0,0)">这种做法虽然保证了数据库的一致性,但对程序来说并不雅观,在程序中如果要判断该属性是否为空,只要判断它是否等于"神奇数字",不得已而为之.</span></p>
</div>
</div>
<img src ="http://www.blogjava.net/kingmove/aggbug/270888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kingmove/" target="_blank">KingMove</a> 2009-05-15 16:50 <a href="http://www.blogjava.net/kingmove/archive/2009/05/15/270888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis 插入空值出现异常</title><link>http://www.blogjava.net/kingmove/archive/2009/05/15/270886.html</link><dc:creator>KingMove</dc:creator><author>KingMove</author><pubDate>Fri, 15 May 2009 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/kingmove/archive/2009/05/15/270886.html</guid><wfw:comment>http://www.blogjava.net/kingmove/comments/270886.html</wfw:comment><comments>http://www.blogjava.net/kingmove/archive/2009/05/15/270886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kingmove/comments/commentRss/270886.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kingmove/services/trackbacks/270886.html</trackback:ping><description><![CDATA[<p>用 iBatis 应用程序连接的数据库是 Oracle, 映射文件中的插入语句写成如下形式&nbsp;</p>
<p>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-xml">
    <li class="alt"><span><span class="comments">&lt;!--&nbsp;插入一条Person对应的记录到数据库中&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span class="tag-name">insert</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"insertPerson"</span><span>&nbsp;&nbsp;</span><span class="attribute">parameterClass</span><span>=</span><span class="attribute-value">"com.unmi.Person"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;INSERT&nbsp;INTO&nbsp;PERSON(ID,NAME,PASSWD)&nbsp;VALUES(#id#,#name#,#passwd#)&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">insert</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<textarea class="xml" style="display: none; width: 100%" name="code" rows="3">&lt;!-- 插入一条Person对应的记录到数据库中 --&gt;
&lt;insert id="insertPerson"  parameterClass="com.unmi.Person"&gt;
INSERT INTO PERSON(ID,NAME,PASSWD) VALUES(#id#,#name#,#passwd#)
&lt;/insert&gt; </textarea> <br />
Person表的三个字段都允许NULL值，当在用如下程序&nbsp;
<p>&nbsp;</p>
<p>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>SqlMapClient&nbsp;sqlMap&nbsp;=&nbsp;SqlMapConfig.getSqlMapInstance();&nbsp;&nbsp;</span><span class="comment">//&nbsp;as&nbsp;coded&nbsp;above&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>Person&nbsp;person&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Person(</span><span class="number">1</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>person.setName(<span class="string">"Unmi"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="comment">//&nbsp;person.setPasswd("123456");&nbsp;//&nbsp;注意该行被注释，让passwd属性为NULL&nbsp;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>sqlMap.insert(<span class="string">"insertPerson"</span><span>,&nbsp;person);&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<textarea class="java" style="display: none; width: 100%" name="code" rows="3">   SqlMapClient sqlMap = SqlMapConfig.getSqlMapInstance();  // as coded above
Person person = new Person(1);
person.setName("Unmi");
// person.setPasswd("123456"); // 注意该行被注释，让passwd属性为NULL
sqlMap.insert("insertPerson", person); </textarea> <br />
执行后程序报错<br />
<font color="#ff0000">Exception in thread "main" </font><font color="#0000ff">com.ibatis.common.jdbc.exception.NestedSQLException</font><font color="#ff0000">:</font>&nbsp;&nbsp; <br />
<font color="#ff0000">--- The error occurred in com/unmi/Person.xml.&nbsp; <br />
--- The error occurred while applying a parameter map.&nbsp; <br />
--- Check the insertPerson-InlineParameterMap.&nbsp; <br />
--- Check the parameter mapping for the 'passwd' property.&nbsp; <br />
--- Cause: </font><font color="#0000ff">java.sql.SQLException</font><font color="#ff0000">: 无效的列类型</font><br />
<font color="#ff0000">Caused by:</font><font color="#0000ff">java.sql.SQLException</font><font color="#ff0000">: 无效的列类型<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(</font><font color="#0000ff">GeneralStatement.java:91</font><font color="#ff0000">)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert(</font><font color="#0000ff">SqlMapExecutorDelegate.java:442</font><font color="#ff0000">)</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert(</font><font color="#0000ff">SqlMapSessionImpl.java:81</font><font color="#ff0000">)<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.insert(</font><font color="#0000ff">SqlMapClientImpl.java:58</font><font color="#ff0000">)<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">at com.unmi.Client.main(</font><font color="#0000ff">Client.java:33</font><font color="#ff0000">)<br />
</font><font color="#ff0000">Caused by:</font><font color="#0000ff">java.sql.SQLException</font><font color="#ff0000">: 无效的列类型<br />
</font>&nbsp;&nbsp;&nbsp; <font color="#ff0000">at oracle.jdbc.dbaccess.DBError.throwSqlException(</font><font color="#0000ff">DBError.java:168</font><font color="#ff0000">)<br />
</font>&nbsp;&nbsp;&nbsp; <font color="#ff0000">at oracle.jdbc.dbaccess.DBError.throwSqlException(</font><font color="#0000ff">DBError.java:210</font><font color="#ff0000">)</font><br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">at oracle.jdbc.dbaccess.DBError.throwSqlException(</font><font color="#0000ff">DBError.java:273</font><font color="#ff0000">)<br />
</font>&nbsp;&nbsp;&nbsp; <font color="#ff0000">at oracle.jdbc.driver.OracleStatement.get_internal_type(</font><font color="#0000ff">OracleStatement.java:4560</font><font color="#ff0000">)</font><br />
&nbsp;&nbsp;&nbsp; <font color="#ff0000">at oracle.jdbc.driver.OraclePreparedStatement.setNull(</font><font color="#0000ff">OraclePreparedStatement.java:869</font><font color="#ff0000">)</font>
<p>&nbsp;</p>
<p>只要去掉 person.setPasswd("123456"); 前的注释，让Person的三个字段都不为NULL，才能成功向数据库中插入记录。其实Person表并没有任何约束，却是iBatis在此拦截下来，实是多此一举。那如果我确实让某个字段是NULL值，该怎么做呢？您只要修改一下映射文件中预置的SQL语句就行了，告诉iBatis当该字段出现NULL 值该用什么值来替代，连接Oracle即使是要求某字段传入NULL值时就是插入NULL值也必须要你累述一遍，好讨厌的事情。</p>
<p>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-xml">
    <li class="alt"><span><span class="comments">&lt;!--&nbsp;插入一条Person对应的记录到数据库中&nbsp;--&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span class="tag-name">insert</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"insertPerson"</span><span>&nbsp;</span><span class="attribute">parameterClass</span><span>=</span><span class="attribute-value">"com.unmi.Person"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;INSERT&nbsp;INTO&nbsp;PERSON(ID,NAME,PASSWD)&nbsp;VALUES(#id#,#name#,#passwd:VARCHAR:NULL#)&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">insert</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<textarea class="xml" style="display: none; width: 100%" name="code" rows="3"> &lt;!-- 插入一条Person对应的记录到数据库中 --&gt;
&lt;insert id="insertPerson" parameterClass="com.unmi.Person"&gt;
INSERT INTO PERSON(ID,NAME,PASSWD) VALUES(#id#,#name#,#passwd:VARCHAR:NULL#)
&lt;/insert&gt; </textarea> <br />
支持的类型在 java.sql.Types 中列示出来了，我一开始还把上面的 VARCHAR 错写成了 VARCHAR2。再比如果你想传入的 id 为NULL时替换为 0, 你就可以写成 #id:INTEGER:0#。
<p>&nbsp;</p>
<p>不知你注意到没有，我们上面的insert标记配置了属性是 parameterClass, 那如果配置的是 parameterMap 该如何解决因字段为NULL值的问题呢？这就要求我们在配置 parameterMap标记中可能出现NULL值的参数一定要指定相应的 jdbcType属性就行。只要不指定nullValue属性就表示在该表这段中直接记下NULL值。</p>
<p>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">parameterMap</span><span>&nbsp;&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"insert-person-paraMap"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.unmi.Person"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">parameter</span><span>&nbsp;</span><span class="attribute">property</span><span>=</span><span class="attribute-value">"id"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">parameter</span><span>&nbsp;</span><span class="attribute">property</span><span>=</span><span class="attribute-value">"name"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">parameter</span><span>&nbsp;</span><span class="attribute">property</span><span>=</span><span class="attribute-value">"passwd"</span><span>&nbsp;&nbsp;</span><span class="attribute">jdbcType</span><span>=</span><span class="attribute-value">"VARCHAR"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="tag">&lt;/</span><span class="tag-name">parameterMap</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="comments">&lt;!--&nbsp;插入一条Person对应的记录到数据库中&nbsp;--&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="tag">&lt;</span><span>&nbsp;</span><span class="tag-name">insert</span><span>&nbsp;</span><span class="attribute">id</span><span>&nbsp;=</span><span class="attribute-value">"insertPerson"</span><span>&nbsp;&nbsp;</span><span class="attribute">parameterMap</span><span>=</span><span class="attribute-value">"insert-person-paraMap"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;INSERT&nbsp;INTO&nbsp;PERSON(ID,NAME,PASSWD)&nbsp;VALUES(?,?,?)&nbsp;&nbsp;</span></li>
    <li class=""><span><span class="tag">&lt;/</span><span class="tag-name">insert</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<textarea class="xml" style="display: none; width: 100%" name="code" rows="3"> &lt;parameterMap  id="insert-person-paraMap" class="com.unmi.Person"&gt;
&lt;parameter property="id"/&gt;
&lt;parameter property="name"/&gt;
&lt;parameter property="passwd"  jdbcType="VARCHAR"/&gt;
&lt;/parameterMap&gt;
&lt;!-- 插入一条Person对应的记录到数据库中 --&gt;
&lt; insert id ="insertPerson"  parameterMap="insert-person-paraMap"&gt;
INSERT INTO PERSON(ID,NAME,PASSWD) VALUES(?,?,?)
&lt;/insert&gt; </textarea> <br />
最后我连接MySql数据库，根本不需要为插入NULL值而考虑设置JDBC类型，平常对待，看来这是iBatis处理Oracle数据库的一个Bug. <br />
<p><br />
<br />
<span style="color: red">今天做程序遇到类似问题,将网上搜索过来的贴于此处.<br />
我的问题:数据库连接是sql server2000,在插入money型字段为空值出现了异常.解决方法是像上面所写的#property:INTEGER:NULL#,设定插入空值.估计应该是数字型的字段插入空值会异常,因为我其它类型字段插入空值却是成功了的.也有人说是驱动的问题,待验证.</span></p>
<img src ="http://www.blogjava.net/kingmove/aggbug/270886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kingmove/" target="_blank">KingMove</a> 2009-05-15 16:46 <a href="http://www.blogjava.net/kingmove/archive/2009/05/15/270886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>