MyBatis 是一款優秀的持久層框架,支援自定義 SQL、存儲過程以及高級映射。它幾乎消除了所有的 JDBC 代碼、參數手動設置及結果集檢索工作。MyBatis 通過簡單的 XML 或註解進行配置與原始映射,將介面和 Java 的 POJO(Plain Old Java Objects,普通 Java 對象)映射為數據庫中的記錄。
MyBatis 最初是 Apache 的開源項目 iBatis,2010 年遷移至 Google Code 並更名為 MyBatis,2013 年 11 月再遷移至 GitHub(項目地址)。iBATIS 一詞源於 "internet" 與 "abatis" 的組合,提供 SQL Maps 和 Data Access Objects(DAO)功能。
每個 MyBatis 應用的核心都是 SqlSessionFactory 實例,可通過 SqlSessionFactoryBuilder 獲取。構建器支持從 XML 配置文件或預定義的配置類實例中創建工廠。
MyBatis Generator 可自動生成 Dao 層、Model 層和 Mapper 層代碼,極大提升開發效率。官方下載地址:MyBatis Generator,中文介紹:中文文檔。
<context id="MySQLTables" targetRuntime="MyBatis3" defaultModelType="conditional">
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver"
connectionURL="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test"
userId="test" password="1234">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="com.ouc.model" targetProject="D:\JavaProject\generator\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.ouc.mapping" targetProject="D:\JavaProject\generator\src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.ouc.dao" targetProject="D:\JavaProject\generator\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<table tableName="V_SupplyUser" domainObjectName="VSupplyUser" ... />
<table tableName="WJ_GateList" domainObjectName="WJGateList" ... />
</context>
java -jar mybatis-generator-core-1.3.2.jar -configfile generator.xml -overwrite
<configuration>
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
<typeAliases>
<typeAlias alias="User" type="com.ouc.mkhl.platform.authority.model.User"/>
<typeAlias alias="Role" type="com.ouc.mkhl.platform.authority.model.Role"/>
</typeAliases>
<typeHandlers>
<typeHandler handler="com.ouc.openplatform.dao.mybatis.SerializableTypeHandler"/>
</typeHandlers>
</configuration>
public class SerializableTypeHandler extends BaseTypeHandler<Serializable> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Serializable parameter, JdbcType jdbcType) throws SQLException {
ps.setObject(i, parameter);
}
@Override
public Serializable getNullableResult(ResultSet rs, String columnName) throws SQLException {
return (Serializable) rs.getObject(columnName);
}
// 其他重寫方法...
}
MyBatis 查詢映射時可使用 resultType 或 resultMap,兩者不可共存。resultMap 是最強大的特性,適用於複雜映射場景。
<resultMap id="UserBaseResultMap" type="User"> <id column="id" property="id" jdbcType="INTEGER" /> <result column="userName" property="userName" jdbcType="VARCHAR" /> <result column="password" property="password" jdbcType="VARCHAR" /> <result column="email" property="email" jdbcType="VARCHAR" /> <result column="trueName" property="trueName" jdbcType="VARCHAR" /> <result column="sex" property="sex" jdbcType="VARCHAR" /> <result column="age" property="age" jdbcType="INTEGER" /> <result column="telephone" property="telephone" jdbcType="VARCHAR" /> </resultMap>
<select id="selectUsers" resultMap="UserBaseResultMap"> select id, userName, email from user </select>
<insert id="saveUser" parameterType="User">
insert into user (userName, password, email, trueName, sex, age, telephone)
values (#{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR},
#{trueName,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}, #{telephone,jdbcType=VARCHAR})
</insert>
<update id="updateUser" parameterType="User">
update user
<set>
<if test="userName != null"> userName = #{userName,jdbcType=VARCHAR}, </if>
<if test="password != null"> password = #{password,jdbcType=VARCHAR}, </if>
<if test="email != null"> email = #{email,jdbcType=VARCHAR}, </if>
<if test="trueName != null"> trueName = #{trueName,jdbcType=VARCHAR}, </if>
<if test="sex != null"> sex = #{sex,jdbcType=VARCHAR}, </if>
<if test="age != null"> age = #{age,jdbcType=INTEGER}, </if>
<if test="telephone != null"> telephone = #{telephone,jdbcType=VARCHAR}, </if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<delete id="deleteUser" parameterType="Integer">
delete from user where id = #{id,jdbcType=INTEGER}
</delete>
<sql id="UserBaseColumnList"> userName, password, email, telephone </sql> <select id="getUsers" resultMap="UserBaseResultMap"> select <include refid="UserBaseColumnList" /> from user </select>
<select id="getUserByName" resultType="User" parameterType="String">
select id, userName, email from user where userName = #{userName,jdbcType=VARCHAR}
</select>
<insert id="saveUser" parameterType="User"> ... </insert>
<select id="selectChildGroupTotalNum" resultType="Integer">
select count(*) from groupinfo
<trim prefix="WHERE" prefixOverrides="AND|OR">
and id in <foreach collection="idStr" item="ids" open="(" separator="," close=")"> #{ids} </foreach>
<if test="name != null and name != '' "> and name LIKE CONCAT(CONCAT('%', #{name}),'%') </if>
<if test="description != null and description != '' "> AND description LIKE CONCAT(CONCAT('%', #{description}),'%') </if>
<if test="type != null and type != -1 "> AND type = #{type,jdbcType=INTEGER} </if>
<if test="category != null and category != -1 "> AND category = #{category,jdbcType=INTEGER} </if>
</trim>
</select>
方式一:按順序傳遞
<select id="selectSensorNobySensorName" resultType="Integer">
select SensorNo from sensorconfig where Name = #{0} and TestunitNo = #{1} and LABCODE = #{2}
</select>
方式二:@Param 註解(推薦)
<select id="selectByUserNameAndVCode" resultMap="UserBaseResultMap">
select id, userName from user
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="userName != null and userName != ''"> and userName LIKE CONCAT(CONCAT('%', #{userName}),'%') </if>
<if test="supplierno != null and supplierno != ''"> and supplierNo LIKE CONCAT(CONCAT('%', #{supplierno}),'%') </if>
and supplierNo != 'test'
</trim>
LIMIT #{startIndex}, #{pageSize}
</select>
MyBatis 動態 SQL 是其最靈活強大的部分,主要標籤包括:
<selectKey>:主鍵生成策略<if>:條件判斷<where> / <set>:智能處理 WHERE/SET 子句<trim>:替代 where/set,自定義前綴後綴<choose>, <when>, <otherwise>:類似 switch-case<foreach>:集合遍歷,構建 IN 子句等<select id="selectTotalNumByAccountType" resultType="Integer">
select count(*) from user
<trim prefix="WHERE" prefixOverrides="AND|OR">
and id not in <foreach collection="idStr" item="ids" open="(" separator="," close=")"> #{ids} </foreach>
<if test="userName != null and userName != ''"> and userName LIKE CONCAT(CONCAT('%', #{userName}),'%') </if>
<if test="supplierno != null and supplierno != ''"> and supplierNo LIKE CONCAT(CONCAT('%', #{supplierno}),'%') </if>
<if test="trueName != null and trueName != ''"> and trueName LIKE CONCAT(CONCAT('%', #{trueName}),'%') </if>
AND accountType = #{accountType}
</trim>
</select>