將ibatis遷移到mybatis3的過程記錄
場景:有些以前的老項目是使用ibatis開發的,現在有轉換成mybatis3的需求。
環境准備:需要安裝Ant,以下是本人的安裝版本,具體怎么安裝不再贅述,就是下載解壓配環境變量,和maven等安裝過程類似,可百度。

工具:ibatis2mybatis 地址:https://github.com/mybatis/ibatis2mybatis
注意下載最新的版本。不要下載release版本,最新版本功能多一點
該工具可以幫你將ibatis 2.x sqlmap文件轉換為myBatis 3.x mapper文件,該工具是使用了Ant構建任務進行XSTL轉換和一些語法文字替換
該工具下載下來使用非常簡單,把你要轉換的所有sqlmap文件放到source文件夾,然后在當前目錄直接運行ant命令即可,轉換成功的mapper文件放在了destination文件夾下。


當然,還需要進行一些個性化配置。
比如根據自己的需要在build.xml文件中配置轉換類型;
| <!-- replace #id:NUMERIC# to #id,jdbcType=NUMERIC# etc. --> <replace dir="destination" includes="*.xml" token=":NUMERIC#" value=",jdbcType=NUMERIC#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":TIMESTAMP#" value=",jdbcType=TIMESTAMP#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":VARCHAR#" value=",jdbcType=VARCHAR#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":BLOB#" value=",jdbcType=BLOB#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":TIME#" value=",jdbcType=TIMESTAMP#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":FLOAT#" value=",jdbcType=FLOAT#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":INTEGER#" value=",jdbcType=INTEGER#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":CLOB#" value=",jdbcType=CLOB#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":DECIMAL#" value=",jdbcType=DECIMAL#" encoding="UTF8"/> <replace dir="destination" includes="*.xml" token=":VARCHAR2#" value=",jdbcType=VARCHAR#" encoding="UTF8"/> <!-- add any needed jdbc type here (for example :CLOB#, :FLOAT#, :REAL#, :BIT#, :INTEGER#, :DECIMAL#, :DATE#, :TIME#, .... ) <replace dir="destination" includes="*.xml" token=":???#" value=",jdbcType=???#" encoding="UTF8"/> |

還有需要在migrate.xstl文件中做一些個性化配置,具體可以查閱XSLT相關語法。
比如針對dynamic做一些處理,當前面有where 1=1 和沒有where 1=1 存在時轉換方法是不一樣的。



| <xsl:template match="dynamic"> <xsl:choose> <xsl:when test="contains(@prepend, 'where')"> <xsl:element name="where"> <xsl:apply-templates/> </xsl:element> </xsl:when> <xsl:otherwise > <xsl:apply-templates/> </xsl:otherwise> </xsl:choose>
</xsl:template> |

還有針對isNotEqual的處理要自己補充:

| <xsl:template match="isNotEqual"> <xsl:element name="if"> <xsl:attribute name="test"> <xsl:value-of select="@property" /><xsl:text> != '</xsl:text> <xsl:value-of select="@compareValue" /><xsl:text>'.toString()</xsl:text> </xsl:attribute> <xsl:value-of select="@prepend" /> <xsl:apply-templates/> </xsl:element> </xsl:template> |
當出現如下情況時isEmpty isNotEmpty分為兩種情況,一種是多參數時的轉換,一種是只有一個默認參數時的轉換,一個參數時的情況如下

需要配置如下代碼:
| <xsl:template match="isNotEmpty"> <xsl:element name="if"> <xsl:attribute name="test"> <xsl:if test="substring-before(@property, '.')"> <xsl:value-of select="substring-before(@property, '.')" /><xsl:text> != null and </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="not(@property)"> <xsl:text>_parameter</xsl:text> </xsl:when> <xsl:otherwise > <xsl:value-of select="@property" /> </xsl:otherwise> </xsl:choose> <xsl:text> != null and </xsl:text> <xsl:choose> <xsl:when test="not(@property)"> <xsl:text>_parameter</xsl:text> </xsl:when> <xsl:otherwise > <xsl:value-of select="@property" /> </xsl:otherwise> </xsl:choose> <xsl:text> != ''</xsl:text> </xsl:attribute> <xsl:value-of select="@prepend" /> <xsl:apply-templates/> </xsl:element> </xsl:template> <xsl:template match="isEmpty"> <xsl:element name="if"> <xsl:attribute name="test"> <xsl:if test="substring-before(@property, '.')"> <xsl:value-of select="substring-before(@property, '.')" /><xsl:text> != null and </xsl:text> </xsl:if> <xsl:choose> <xsl:when test="not(@property)"> <xsl:text>_parameter</xsl:text> </xsl:when> <xsl:otherwise > <xsl:value-of select="@property" /> </xsl:otherwise> </xsl:choose> <xsl:text> == null or </xsl:text> <xsl:choose> <xsl:when test="not(@property)"> <xsl:text>_parameter</xsl:text> </xsl:when> <xsl:otherwise > <xsl:value-of select="@property" /> </xsl:otherwise> </xsl:choose> <xsl:text> == ''</xsl:text> </xsl:attribute> <xsl:value-of select="@prepend" /> <xsl:apply-templates/> </xsl:element> </xsl:template> |
Xstl中關於是否是null的判斷語法格式如下:
| <xsl:if test=" USERNAME "> USERNAME is not null </xsl:if> <xsl:if test="not(USERNAME)"> USERNAME is null </xsl:if> <xsl:if test="USERNAME =''"> USERNAME is empty string </xsl:if> <xsl:if test="USERNAME!=''"> USERNAME is not empty string </xsl:if> |
另外遇到mybatis中傳參數的幾個小問題:
1 當MyBatis 判斷條件為等於的時候,常量需要加 .toString() 來轉換,因為mybatis會把' '解析為Char,而傳入的是String類型,java是強類型語言,所以不等。
以下8,2,3,4,5均可以,6 直接報語法錯誤,unitId == '1' 和jcbh == '7' 在unitId=1 和jcbh=7 時也不會執行,9也不會執行。
| <if test='tblx != null and tblx== "8" '> AND tblx = #{tblx,jdbcType=VARCHAR} </if> <if test="unitId!=null and unitId == '1' "> AND unit_id=#{unitId,jdbcType=INTEGER} </if> <if test="jctbisreturn!=null and jctbisreturn == '2'.toString()" > AND jctbisreturn=#{jctbisreturn,jdbcType=INTEGER} </if> <if test="userId!=null and userId == 3 "> AND user_id=#{userId,jdbcType=INTEGER} </if> <if test="townCode!=null and townCode!='4'.toString()"> AND town_code=#{townCode,jdbcType=VARCHAR} </if> <if test="xzqdm!=null and xzqdm=='5'.toString()"> AND xzqdm=#{xzqdm,jdbcType=VARCHAR} </if> <if test="xmc!=null and xmc==6.toString()"> AND xmc=#{xmc,jdbcType=VARCHAR} </if> <if test="jcbh != null and jcbh == '7' "> AND jcbh = #{jcbh,jdbcType=VARCHAR}, </if> <if test="townCode!=null and townCode!='9'"> AND town_code=#{townCode,jdbcType=VARCHAR} </if> |
另外:
| <if test="townCode!=null and townCode==''"> AND town_code=#{townCode,jdbcType=VARCHAR} </if> <if test="townCode!=null and townCode==''.toString()"> AND town_code=#{townCode,jdbcType=VARCHAR} </if>
當輸入 String townCode="" 上面的兩個語句都可以執行,當為空字符串時可以不用''.toString(),可以簡寫為''即可 |
2 MyBatis在使用單個參數進行if條件判斷的時候,如果直接使用參數本身,則會報出:There is no getter for property named ... 的異常,比如
| <select id="testStringParam2" resultMap="BaseResultMap"> SELECT * FROM j_jctb <where> <if test="tblx!= null and tblx!= ''"> AND tblx = #{value,jdbcType=VARCHAR} </if> </where> </select> |
正確的方法是應該用"_parameter"來代替需要判斷的參數:
| <select id="testStringParam2" resultMap="BaseResultMap"> SELECT * FROM j_jctb <where> <if test="_parameter != null and _parameter != ''"> AND tblx = #{value,jdbcType=VARCHAR} </if> </where> </select> |
當然,還有一種方法就是在Mapper接口中給定參數名,如:
| JJctb testStringParam2(String tblx) throws Exception ; 改為: JJctb testStringParam2(@Param("tblx") String tblx) throws Exception ; |
中途遇到關於mybatis傳遞多個實體參數的問題,可采用如下寫法:以@Param綁定,以對象名.(點)對象屬性名的方式調用就可以了。
| abstract JJctb testStringParam3( @Param("jctb") JJctb jctb , @Param("yuser") YUser yuser, @Param("tblx") String tblx) throws Exception ; <select id="testStringParam3" resultMap="BaseResultMap"> SELECT * FROM j_jctb <where> <if test="jctb.jcbh != null and jctb.jcbh != ''"> AND jcbh = #{jctb.jcbh,jdbcType=VARCHAR} </if> <if test="yuser.username != null and yuser.username != ''"> AND username = #{yuser.username,jdbcType=VARCHAR} </if> <if test="tblx != null and tblx != ''"> AND tblx = #{tblx,jdbcType=VARCHAR} </if>
</where> </select> |
參考博文:http://blog.csdn.net/lanxuezaipiao/article/details/52902074
http://blog.csdn.net/shenzhenNBA/article/details/46673327
