mybatis使用小貼士

分享了以下tips:

一、事務管理
二、xml配置sql代碼段
三、#和$的區別
四、注意對<、>做轉義
五、依據字符串是否爲空,動態組織sql語句
六、使用自定義的類型轉換器
七、resultMap的複用


一、事務管理

用戶執行一個動作,後臺需依次更新多個表,如果其中有一個更新失敗,則要回滾之前的更新。這種情況,就是事務回滾。
要支持事務操作,需要:

1、確保數據庫表的類型是InnoDB,而不是MyISAM

(MyISAM不支持事務,這是一個坑,之前總結過 http://blog.csdn.net/lizeyang/article/details/9280253)

2、所有更新操作完成後,再執行commit

例如:
SqlSession session = getSqlSession();
int sqlResult = session.insert("insert a table", po);
int sqlResult = session.update("update b table", po);
//這時,前面的insert和update還沒真正執行
session.commit();
//commit後,db才真正更新
session.close();

 

二、xml配置sql代碼段

mybatis需要通過xml配置每次db操作的sql語句。如果多個sql語句中,包含了相同的sql語段,怎麼辦呢?複製粘貼?這顯然不是一個好習慣。建議配置代碼段,然後每個sql直接引用這個代碼段。
語法:

1、在xml中先用<sql>這個標籤,包裝代碼段,配置id

     <sql id="getFeedBackList_fragment">
from t_comment where refer_type = #{type} and
refer_id = #{referId} 
     </sql>

2、在需要這個代碼段的地方,通過<include refid="id"/>語句,引入這個sql

例如
<select id='getFeedBackList' parameterType='map' resultMap='feeback'>
select id
<include refid="getFeedBackList_fragment"/>
order by
create_time desc
</select>


三、#和$的區別

當sql中有一些參數,需要調用時動態傳入時,就需要在sql中寫變量,調用時再傳入變量。mybatis中,#和$,都是變量的修飾符。一般推薦用#。
#相當於jdbc中,對prepareStatement做set參數的操作,而$則相當於拼接了sql語句,再執行statament。prepareStatement、statament的區別,具體可以在網上搜下,這裏就不贅述了。

四、注意對<、>做轉義

其實,寫xml文件,都得注意這個問題,要將>轉義成&gt; 要將<轉義成&lt;  。我們在寫sql時,經常要用到<、>來篩選sql結果,更要牢記這個注意項。

五、依據字符串是否爲空,動態組織sql語句

mabatis xml配置sql,對字符串的處理能力不夠強大,對於判空這樣常見的需求,還是得通過para!= null and para != ''來完成,沒有相關的內建函數。
<if test="para!= null and para != '' ">sql語句</if>

六、使用自定義的類型轉換器

假設有一個字段,數據庫字段類型,是timestamp,當賦值到javabean時,希望變成對應的long值。怎麼做呢?最原生態的一種選擇,賦值給bean時,就是timestamp類型,之後再重新遍歷數據,改成long值。這種做法,顯然很搓,增加了業務邏輯的代碼量,不利於轉化邏輯複用。
其實,mybatis本身就支持自定義類型轉換器,可以很好地支持這種需求。這裏主要想告訴你,mybatis是有這種能力的,更詳細的內容,可以再看官方教程。這裏簡單貼下我的示例。

1、configuration xml文件配置

<configuration>
 ……

<typeHandlers>
<typeHandler handler="test.TimeTypeHandler"
javaType="Long" jdbcType="TIME" />
</typeHandlers>
……
</configuration>

2、自定義類型轉換器

上面的handle爲test.TimeTypeHandler,因此工程中,要寫對應的test.TimeTypeHandler.java。轉換邏輯,就在這個java文件中
package test;
public class TimeTypeHandler implements TypeHandler<Long>
{
private final String TIME_TYPE = "yyyy-MM-dd HH:mm:ss";

public long strToLongTime(String dateStr)
{
if (null == dateStr)
return 0L;

SimpleDateFormat sdf = new SimpleDateFormat(TIME_TYPE);
Date date = new Date();
try
{
date = sdf.parse(dateStr);
}
catch (ParseException e)
{
e.printStackTrace();
}
if (date == null)
return 0L;

System.out.println(date);
return date.getTime();
}

public Long getResult(ResultSet arg0, String arg1) throws SQLException
{
String datestr = arg0.getString(arg1);
return strToLongTime(datestr);
}

public Long getResult(ResultSet arg0, int arg1) throws SQLException
{
String datestr = arg0.getString(arg1);
return strToLongTime(datestr);
}

public Long getResult(CallableStatement arg0, int arg1) throws SQLException
{
String datestr = arg0.getString(arg1);
return strToLongTime(datestr);
}

public void setParameter(PreparedStatement arg0, int arg1, Long arg2, JdbcType arg3) throws SQLException
{
if (arg2 == null)
{
arg2 = 0L;
}

Date date = new Date(arg2);
SimpleDateFormat sdf = new SimpleDateFormat(TIME_TYPE);
String datetime = sdf.format(date);
arg0.setString(arg1, datetime);
}

}

 

3、mapper xml配置

<mapper namespace="xxxx">
……
     //這裏定義了ExpDownloadPo這個sql查詢結果,要映射到java bean :test.ExpDownloadPo
<resultMap id="ExpDownloadPo"  type="test.ExpDownloadPo">
<id property="id" column="id" />
               //first_download_time這個數據,在賦值到firstDownloadTime時,要轉轉換,從jdbc的time型,轉換成javaType的long型,具體怎麼轉換,因爲前面第一點,定義了<typeHandlers><typeHandler handler="test.TimeTypeHandler" javaType="Long" jdbcType="TIME" /></typeHandlers>,因此會自動使用test.TimeTypeHandler這個轉換器

<result property="firstDownloadTime" column="first_download_time" javaType="Long" jdbcType="TIME"/>
<result property="lastDownloadTime" column="last_download_time" javaType="Long" jdbcType="TIME"/>
</resultMap>
……
</mapper >

 



七、resultMap的複用

我們一般會定義多個mapper.xml文件,將不同的功能,放到不同的xml中。如果mapper文件A需要使用mapper文件B中所定義的resultmap時,是可以直接使用的,請勿在文件B中重複定義resultmap。
具體使用方法是:
例如mapper A的namespace是com.blog.test,其中定義的resultmapid是testbean,那麼,在文件B中,如果要用到這個resultmap,則用它的全名即可,也就是com.blog.test.testbean(namespace+resultmapid)

mapper文件A

<mapper namespace="com.blog.test">
……
<resultMap id="testbean"  ></resultMap>
</mapper>

mapper文件B

<mapper namespace="B">
<select id="mysql" parameterType="map" resultMap="com.blog.test.testbean">
</mapper>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章