Mybatis全攻略(通俗易懂,99%手敲)
第一篇原创技术博客就贡献给MyBatis了,第一是MyBatis本身比较简单,第二是因为MyBatis扩展的点比较多,多挖挖坑,有助于激励今后继续创作,第三是MyBatis确实比较重要吧,毕竟在JAVA界,和Hibernate算是关系型数据库框架的双子星了。
本文旨在让新手小白也能快速上手,所以从最基本的讲起,如果您是中手或者高手,可以跳到响应章节查漏补缺。
文章目录
什么是MyBatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
简单来说其实就是简化了原始JDBC的操作,定制化 SQL其实就是支持手写SQL、存储过程以及高级映射后面再说。当然,其实MyBatis也仅支持手写SQL,所以和Hibernate比起来,他算半自动化框架。
为什么要用MyBatis
这个问题相当简单,如果你写过原生JDBC,那么你肯定知道手写连接数据库那几步操作的酸爽,这种通用的代码写了一遍又一遍,我们程序员还有什么生产力么?所以为了解放生产力,各式各样的框架就诞生了,让我们更专注于业务逻辑代码。
MyBatis的使用方式
传统的项目结构为:配置文件.xml–>各式各样的Map映射文件.xml–>SQLSession工厂类–>实际调用
- 配置文件.xml ======用于设置账户名密码等等基础的配置
- 各式各样的Map映射文件.xml =====用于写真正的SQL语句
- SQLSession工厂类 ======便于调用SQLSession来执行SQL
笔者这次用Spring整合MyBatis作演示,
配置文件.xml 变为java配置类
各式各样的Map映射文件 简化为mapper配置类
SQLSession工厂类 置于配置类之中
java配置类
@Configuration
@MapperScan(value="BatisMapper")
public class DaoConfig {
@Value("${jdbc.driver}")
private String driverClass;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String jdbcUrl;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setUrl(jdbcUrl);
return dataSource;
}
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
dataSource:数据源,算是连接数据库的老四样了:
- driverClass:数据库驱动类型
- user:用户名
- password:密码
- jdbcUrl:数据库url地址
DataSourceTransactionManager :
事务管理器,spring的声明式事务编程要配置事务管理器,由于和文章内容无关,暂不深入说明。
sqlSessionFactory:
不需要再手动写SQLSession工厂类啦,由Spring自动注入
注意下面注解,该注解用于扫描mapper类
@MapperScan(value="BatisMapper")
mapper配置类
@Component
public interface UserMapper {
@Select("SELECT * FROM users WHERE username = #{name}")
@Results(id = "userResult", value = {
@Result(property = "name", column = "username"),
@Result(property = "password", column = "password")
})
User getUser(@Param("name") String name);
@Insert("INSERT INTO student(name,age) VALUES ('jeff',19)")
void insertUser();
}
可以看到这里有两条SQL,一条查询SQL,一条插入SQL
因为现在还没讲那些注解,暂时对Mapper类有个大致印象就好
重点,难点
Mapper配置详解
基本注解:@Select@Insert@Delete@Update
这几种注解对应了基本的增删改查操作,在mapper配置类的方法上打上任意注解与SQL语句,即可在外调用
@Insert("INSERT INTO student(name,age) VALUES ('jeff',19)")
void insertUser();
占位符#{}与${}
相信大家都知道预编译SQL,请看下面例子
@Update("UPDATE student SET name=#{name} WHERE id=${id}")
void updateUser(@Param("name") String name,@Param("id") Long id);
}
当我们需要根据方法入参动态执行SQL时,可以在SQL语句中写#{}与${},并在方法入参中用注解映射。即然#{}与${}都可以预编译SQL,那么区别是什么呢?
当我们执行上述方法时,后台打印的SQL是:
updateUser(“jeff”,1);=====>
UPDATE student SET name=? WHEREid= 2
可见#{}会编译为?占位符
而${}会根据方法传入的量编译为对应的值
知道了这一点,那么两者就很好理解了:
#{}因为会编译为?,所以可以防SQL注入;
${}因为会直接编译为原值,所以不能防止SQL注入,所以别在用户输入的变量上用
${}。在不支持预编译的地方,比如想动态的查表名,则可使用${}来增加SQL的扩展性
比如:
@Update("UPDATE ${tablename}student SET name=#{name} WHERE id=${id}")
void updateUser2(@Param("tablename") String tablename,@Param("name") String name,@Param("id") Long id);
}
@ResultMap与@ResultType
众所周知,增删改查里最难的就是查询了,当我们把查询出的结果映射为一个对象,比如下图代码,都想把查询结果映射为一个User对象,
@Select("SELECT * FROM users WHERE username = #{name}")
@Results(id = "userResult", value = {
@Result(property = "name", column = "username"),
@Result(property = "password", column = "password")
})
User getUser(@Param("name") String name);
@Select("SELECT * FROM users WHERE username = #{name}")
@ResultType(value = User.class)
User getUser2(@Param("name") String name);
}
MyBatis特性:动态标签
动态标签算是MyBatis的一个特性了,非常有意思,
往常我们写动态SQL时,需要写大量的if…else来生成SQL语句,非常不优雅,也非常容易出错
而且试想这一种情况,如果你在WHERE 后面的判断都为否,那么极有可能变成
SELECT * FROM users WHERE这种不符合语法格式的,
一种不优雅的解决方案是写死一个WHERE后的条件:
1=1,让SQL变为SELECT * FROM users WHERE 1=1,但这种方式确实不优雅
而MyBatis为了解决这个问题,提供了一系列的MyBatis动态标签
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
if
标准格式
<if test='startNo!=null '>
SQL语句。。。
</if>
当test的条件为true时,才会拼接标签内的SQL语句
@Select("<script>"
+ "SELECT * FROM "
+ "users WHERE username = #{name}"
+ "<if test='startNo!=null '>"
+ "AND startNo=#{startNo}"
+ "</if>"
+"</script>")
@ResultType(value = User.class)
User getUser2(@Param("name") String name, @Param("startNo") Integer pageNo);
choose, when, otherwise
标准格式
<choose>
<when test=“title != null”>
SQL1
</when>
<when test=“author != null and author.name != null”>
SQL2
</when>
<otherwise>
SQL3
</otherwise>
</choose>
类似java的Switch语句,挨个判断when标签中test表达式的值,若都不满足,则生成otherwise标签的
@Select("<script>"
+ "SELECT * FROM "
+ "users WHERE username = #{name}"
+ "<choose>"
+ "<when test='startNo!=null '>"
+ "AND startNo=#{startNo}"
+ "</when>"
+ “<otherwise>”
+ "AND 1=2"
+ "</otherwise>"
+"</script>")
@ResultType(value = User.class)
User getUser2(@Param("name") String name, @Param("startNo") Integer pageNo);
trim, where, set
这三个感觉用处不大,略过,感兴趣可以自己研究。
foreach
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如
标准格式:
<select id=“selectPostIn” resultType=“domain.blog.Post”>
SELECT *
FROM POST P
WHERE ID in
<foreach item=“item” index=“index” collection=“list”
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
MyBatis存储过程:
待填坑(2019.4.26)

本文详细介绍了MyBatis框架的基本概念、使用原因及配置方法,包括java配置类、mapper配置类,以及各种注解和动态SQL标签的使用技巧,适合初学者快速上手。
4万+

被折叠的 条评论
为什么被折叠?



