src/main/java
├── cn.happy.entity # 實體類
├── cn.happy.dao # Mapper 接口
├── cn.happy.dao.impl # 實現類(可省略,接口綁定 XML)
├── cn.happy.util # 工具類
└── cn.happy.service # 業務層
src/main/resources
├── mybatis-config.xml # 全局配置
├── cn/happy/dao/*.xml # SQL 映射文件
└── log4j.properties # 日志配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 類型別名:包掃描,免寫全限定名 -->
<typeAliases>
<package name="cn.happy.entity"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="happy"/>
<property name="password" value="1"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/happy/dao/StudentMapper.xml"/>
<!-- 生產建議:包掃描 -->
<package name="cn.happy.dao"/>
</mappers>
</configuration>
<mapper namespace="cn.happy.dao.StudentMapper">
<resultMap id="studentMap" type="Student">
<id property="stuno" column="stuno"/>
<result property="stuname" column="stuname"/>
<result property="stuage" column="stuage"/>
<result property="studate" column="studate"/>
</resultMap>
<!-- 插入 + 返回主鍵 -->
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuno">
INSERT INTO student(stuname, stuage, studate)
VALUES(#{stuname}, #{stuage}, #{studate})
</insert>
<!-- 全量查詢 -->
<select id="findAll" resultMap="studentMap">
SELECT * FROM student
</select>
<!-- 模糊查詢:#{ } 預編譯防注入,${ } 字符串拼接 -->
<select id="findByNameLike" resultMap="studentMap">
SELECT * FROM student
WHERE stuname LIKE CONCAT('%', #{stuname}, '%')
</select>
<!-- 刪除 -->
<delete id="deleteById">
DELETE FROM student WHERE stuno = #{id}
</delete>
<!-- 動態更新:僅更新非空字段 -->
<update id="updateStudent">
UPDATE student
<set>
<if test="stuname != null">stuname = #{stuname},</if>
<if test="stuage != null">stuage = #{stuage},</if>
<if test="studate != null">studate = #{studate}</if>
</set>
WHERE stuno = #{stuno}
</update>
</mapper>
// Student.java
@Data @NoArgsConstructor @AllArgsConstructor
public class Student {
private Integer stuno;
private String stuname;
private Integer stuage;
private Date studate;
}
// StudentMapper.java
public interface StudentMapper {
int insertStudent(Student student);
List findAll();
List findByNameLike(String name);
int deleteById(Integer id);
int updateStudent(Student student);
}
@Configuration
@MapperScan("cn.happy.dao") // 掃描 Mapper 接口自動創建代理
public class MyBatisConfig {
@Bean
public DataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
ds.setUsername("happy"); ds.setPassword("1");
return ds;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:cn/happy/dao/*.xml"));
bean.setTypeAliasesPackage("cn.happy.entity");
return bean.getObject();
}
@Bean
public DataSourceTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Service
@Transactional
public class StudentService {
@Autowired StudentMapper studentMapper;
public Student create(Student s) {
studentMapper.insertStudent(s); // 回填主鍵
return s;
}
public Page search(String name, int page, int size) {
PageHelper.startPage(page, size); // 分頁插件
return (Page) studentMapper.findByNameLike(name);
}
}
| 特性 | 關鍵點 | 示例 |
|---|---|---|
| 關聯查詢 | <resultMap> + <association>/<collection> | 一對一、一對多、多對多 |
| 動態 SQL | if/choose/where/set/foreach/trim | 靈活構建 WHERE/SET/IN 子句 |
| 緩存 | 一級緩存、二級緩存、<cache>/<cache-ref> | 查詢緩存、引用緩存 |
| 分頁插件 | PageHelper / MyBatis-Plus | PageHelper.startPage(1,10) |
| 類型處理器 | 實現 TypeHandler | JSON、枚舉、加密字段自動轉換 |
| 批量操作 | ExecutorType.BATCH + foreach | 大批量插入優化 |
#{ } 預編譯參數化(防注入),${ } 字符串拼接(用於表名、排序字段等不可參數化處)resultMap,避免列名與屬性名不匹配導致字段為 nullResultHandler 流式處理,避免 OOMlog4j.logger.cn.happy.dao=trace,改為 info/warnMyBatis 以「SQL 掌控在手、映射靈活透明」著稱。掌握動態 SQL、結果映射、Spring 整合、分頁插件,即可應對 90% 企業級持久化場景。建議新項目直接上 MyBatis-Plus,內置 CRUD、分頁、代碼生成器,開發效率再提升一個檔次。