MyBatis 是優秀的持久層框架,支持普通 SQL、存儲過程、高級映射。消除幾乎所有 JDBC 代碼、手工設置參數、結果集封裝。可用 XML 或註解配置映射,將接口與 POJO 映射為數據庫記錄。
定位:JDBC → DbUtils → MyBatis → Hibernate(半自動 ORM,SQL 可控)
mybatis-3.x.jar、mysql-connector-java.jarusers(id, name, age) 插入測試數據conf.xml:數據源、事務管理器、環境UseruserMapper.xml:<select id="getUser" parameterType="int" resultType="User">select * from users where id=#{id}</select>conf.xml 註冊 mapper:<mapper resource=".../userMapper.xml"/>SqlSessionFactory → SqlSession → selectOne(statement, 1)<insert id="insertUser" parameterType="User">
insert into users(name, age) values(#{name}, #{age})
</insert>
<delete id="deleteUser" parameterType="int">
delete from users where id=#{id}
</delete>
<update id="updateUser" parameterType="User">
update users set name=#{name}, age=#{age} where id=#{id}
</update>
<select id="selectUser" parameterType="int" resultType="User">
select * from users where id=#{id}
</select>
<select id="selectAllUsers" resultType="User">
select * from users
</select>
public interface UserMapper {
@Insert("insert into users(name, age) values(#{name}, #{age})")
int insertUser(User user);
@Delete("delete from users where id=#{id}")
int deleteUserById(int id);
@Update("update users set name=#{name}, age=#{age} where id=#{id}")
int updateUser(User user);
@Select("select * from users where id=#{id}")
User getUserById(int id);
@Select("select * from users")
List<User> getAllUser();
}
conf.xml 註冊:<mapper class="...UserMapper"/>
| 優化點 | 配置示例 |
|---|---|
| 外部化數據源 | <properties resource="db.properties"/> 引用 ${driver} 等 |
| 類型別名 | <typeAliases><typeAlias type="User" alias="_User"/></typeAliases> |
| 日誌輸出 | 加入 log4j.jar + log4j.properties/xml 配置 |
-- 表 orders(order_id, order_no, order_price)
-- 實體 Order(id, orderNo, price)
-- 方式一:SQL 別名
<select id="selectOrder" resultType="_Order">
select order_id id, order_no orderNo, order_price price from orders where order_id=#{id}
</select>
-- 方式二:resultMap 映射
<select id="selectOrder" resultMap="orderResultMap">
select * from orders where order_id=#{id}
</select>
<resultMap type="_Order" id="orderResultMap">
<id property="id" column="order_id"/>
<result property="orderNo" column="order_no"/>
<result property="price" column="order_price"/>
</resultMap>
<!-- 嵌套結果:單次連表查詢 -->
<resultMap type="_Classes" id="classResultMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="_Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<!-- 嵌套查詢:分步查詢,支持延遲加載 -->
<resultMap type="_Classes" id="classResultMap2">
<association property="teacher" column="teacher_id" select="getTeacher"/>
</resultMap>
<select id="getTeacher" parameterType="int" resultType="_Teacher">
select t_id id, t_name name from teacher where t_id=#{id}
</select>
<collection property="students" ofType="_Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
-- 嵌套查詢版
<collection property="students" column="c_id" ofType="_Student" select="getStudents"/>
<select id="getUser" parameterType="ConditionUser" resultType="User">
select * from d_user where age >= #{minAge} and age <= #{maxAge}
<if test='name != null and name != ""'>
and name like #{name}
</if>
</select>
常用標籤:<if>、<choose/when/otherwise>、<trim>、<where>、<set>、<foreach>
<select id="getCount" statementType="CALLABLE" parameterMap="getCountMap">
call mybatis.get_user_count(?,?)
</select>
<parameterMap type="Map" id="getCountMap">
<parameter property="sex_id" mode="IN" jdbcType="INTEGER"/>
<parameter property="user_count" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
| 特性 | 一級緩存 | 二級緩存 |
|---|---|---|
| 作用域 | SqlSession | Mapper (Namespace) |
| 存儲 | HashMap (PerpetualCache) | HashMap / Ehcache 等 |
| 生命周期 | Session 關閉/清理失效 | 應用級,可配置刷新 |
| 開啟方式 | 默認開啟 | mapper 中 <cache/> |
| 失效觸發 | C/U/D 操作 | C/U/D 操作 |
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
mybatis-spring, spring-jdbc, spring-tx, spring-context, spring-test, mysql-connector
<!-- 1. 數據源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 2. SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.domain"/>
</bean>
<!-- 3. Mapper 掃描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- 4. 事務管理 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
public interface UserMapper {
void save(User user);
User findById(int id);
List<User> findAll();
}
<mapper namespace="com.mapper.UserMapper">
<resultMap id="userResult" type="User">...</resultMap>
<insert id="save" keyColumn="user_id" keyProperty="id" useGeneratedKeys="true">...</insert>
<select id="findById" resultMap="userResult">...</select>
<select id="findAll" resultMap="userResult">...</select>
</mapper>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/beans.xml")
public class SMTest {
@Autowired UserMapper userMapper;
@Test public void save() { ... }
@Test public void findAll() { ... }
}
MyBatis 以「SQL 可控、映射靈活、學習曲線平緩」著稱。掌握 resultMap 解決字段映射、association/collection 處理關聯、動態 SQL 構建複雜查詢、一二級緩存優化性能、Spring 整合實現聲明式事務,即可應對絕多數企業級持久層開發需求。