- MyBatis是一款优秀的持久层框架,用于简化JDBC开发
- MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github
- 官网:https://mybatis.org/mybatis-3/zh/index.html
持久层
- 负责将数据到保存到数据库的那一层代码
- JavaEE三层架构:表现层、业务层、持久层
框架
- 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
- 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
1.硬编码
- 注册驱动,获取连接
- SQL语句
2.操作繁琐
- 手动设置参数
- 手动封装结果集
MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作
MyBatis快速入门-
创建表mybatisdemo数据库,创建user表,添加数据
-
创建模块,导入坐标
//pro.xml
4.0.0 org.jihua mavendemo 1.0-SNAPSHOT 17 17 mysql mysql-connector-java 5.1.34 com.alibaba druid 1.1.12 junit junit 4.13 test org.mybatis mybatis 3.5.5 org.slf4j slf4j-api 1.7.20 ch.qos.logback logback-classic 1.2.3 ch.qos.logback logback-core 1.2.3 -
编写MyBatis核心配置文件---->替换连接信息解决硬编码问题
//mybatis-config.xml
-
编写SQL映射文件---->统一管理sql语句,解决硬编码问题
//UserMapper.xml
select * from tb_user -
编码
(1) 定义POJO类
//User类 package com.jihua.pojo; public class User { private Integer id; private String username; private String password; private String gender; private String addr; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + ''' + ", password='" + password + ''' + ", gender='" + gender + ''' + ", addr='" + addr + ''' + '}'; } }(2) main方法内
//mybatisDemo类 package com.demo; import com.jihua.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; public class mybatisDemo { public static void main(String[] args) throws Exception { //1.加载mybatis的核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象,用它来执行sql SqlSession sqlSession = sqlSessionFactory.openSession(); //3. 执行sql Listusers = sqlSession.selectList("demo.selectAll"); System.out.println(users); //4. 释放资源 sqlSession.close(); } }
目的
- 解决原生方式中的硬编码
- 简化后期执行SQL
使用Mapper 代理方式完成入门案例
-
定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置
同—目录下-
新建UserMapper接口,放在src/main/java/com/jihua/Mapper下
-
将UserMapper.xml文件放在src/main/resources/com/jihua/Mapper下
- 注意:在resources目录下创建多级目录不能用.,要用/,例如创建包时可以使用com.jihua.Mapper,但是resources目录只能使用com/jihua/Mapper
-
-
设置SQL映射文件的namespace属性为Mapper接口全限定名
//UserMapper.xml
-
在 Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
//UserMapper接口 package com.jihua.Mapper; import com.jihua.pojo.User; import java.util.List; public interface UserMapper { ListselectAll(); } -
main方法中
//mybatisDemo类 package com.demo; import com.jihua.Mapper.UserMapper; import com.jihua.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; public class mybatisDemo { public static void main(String[] args) throws Exception { //1.加载mybatis的核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象,用它来执行sql SqlSession sqlSession = sqlSessionFactory.openSession(); //3. 执行sql //3.1 通过SqlSession的getMapper方法获取Mapper接口的代理对象 UserMapper UserMapper = sqlSession.getMapper(UserMapper.class); //3.2 调用对应方法完成sql的执行 Listusers = UserMapper.selectAll(); System.out.println(users); //4. 释放资源 sqlSession.close(); } }
细节:如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载
//mybatis-config.xml文件下的mappers修改为MyBatis核心配置文件
MyBatis核心配置文件的顶层结构如下:.
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory (对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseldProvider (数据库厂商标识)
- mappers(映射器)
类型别名(typeAliases)
细节:配置各个标签时,需要遵守前后顺序
配置文件完成增删改查- 要完成的功能列表清单:
- 查询
- 查询所有数据
- 查看详情
- 条件查询
- 添加
- 修改
- 修改全部字段
- 修改动态字段
- 删除
- 删除一个
- 批量删除
- 查询
数据库表的字段名称和实体类的属性名称不一样,则不能自动封装数据
-
起别名:对不一样的列名起别名,让别名和实体类的属性名一样
-
缺点:每次查询都要定义一次别名
select id, use_name as useName from tb_use;
-
-
sql片段
-
缺点:不灵活
id, use_name as neme select from tb_user;
-
-
resultMap
1.定义标签
2.在标签中,使用resultMap属性替换resultType属性resultMap属性:
- id:唯一标识
- type:映射的类型,支持别名
resultMap内部:
-
id:完成主键字段的映射
- column:表的列名
- property:实体类的属性名
-
result:完成一般字段的映射
- column:表的列名
- property:实体类的属性名
参数占位符:
- #{ }:会将其替换为?,为了防止SQL注入
- ${ }:拼sql。会存在SQL注入问题
- 使用时机:
- 参数传递的时候:#{ }
- 表名或者列名不固定的情况下:${}。会存在SQL注入问题
参数类型: parameterType:可以省略
使用方法:
//4.执行方法 User user = userMapper.selectById(id); system.out.println(user);
同时接口里应该有方法:
User selectById(int id);
特殊字符处理:
-
转义字符:例如<表示<
-
CDATA区:IDEA中敲CD直接回车
sql语句:
参数接收
-
散装参数:
如果方法中有多个参数,需要使用@Param( “SQL参数占位符名称”)
List
selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName); -
对象参数:
接收前端传入的数据后,封装为一个对象,其中对象的属性名称要和参数占位符名称一致
List
selectByCondition(Brand brand); -
map集合参数:
接收前端传入的数据后,封装为一个map集合,其中键的名称要和参数占位符名称一致
List
selectByCondition(Map map) ;
当用户查询时并没有用到所有条件限制时,要采用动态SQL
SQL语句会随着用户的输入或外部条件的变化而变化,我们称为动态SQL
MyBatis 对动态SQL有很强大的支撑:
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
上面的代码如果第一个参数也没有传入,会导致拼接的sql语法错误
解决方法:
-
恒等式
添加一个1=1条件
-
替换where关键字
mybatis自带的条件处理
-
从多个条件中选择一个
-
choose (when, otherwise):选择,类似于Java中的switch语句
MyBatis事务:
在获取sqlSession对象时
//2.获取SqlSession对象,用它来执行sql SqlSession sqlSession = sqlSessionFactory.openSession();
openSession():默认开启事务,进行增删改操作后需要使用sqlSession.commit();手动提交事务
openSession(true):可以设置为自动提交事务(关闭事务)
在数据添加成功后,需要获取插入数据库数据的主键的值
只需要添加两个属性:
useGeneratedKeys:开启主键返回
keyProperty:指向对应主键名称
修改insert into tb_order (payment,paymlent_type,status) values (#{payment},#{paymentType},#{status});
:
使用set标签处理参数个数导致的sql语法问题
删除update tb_brand where id = #{id}; brand_name = #{brandName}, company_name = #{companyName}, ordered = #{ordered}, description = #{description}, status = #{status},
delete from tb_brand where id =#{id}; delete>
-
批量删除
传入一个id的数组
delete from tb_brandwhere id in (?,?,?) mybatis会将数组参数,封装为一个Map集合
-
默认::array =数组
-
或者:使用@Param注解改变map集合的默认key的名称
//定义接口方法时 void deleteByIds (@Param("ids") int[] ids);
in(?, ?, ?)中具体有多少个?,需要遍历数组,需要使用标签
delete from tb_brand where id in #{id} separator属性表示自动添加分隔符,open和close属性会加在开始和结束的位置
-
MyBatis 接口方法中可以接收各种各样的参数,MyBatis底层对于这些参数进行不同的封装处理方式
MyBatis参数封装:
MyBatis提供了ParamNameResolver类来进行参数封装
- 单个参数
-
POJO(数据结构)类型:直接使用,属性名和参数占位符名称一致
-
Map集合:直接使用,键名和参数占位符名称一致
-
Collection:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map .put( "arg0" ,list集合); map.put( "collection " ,list集合);
-
List:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map .put( "arg0" ,list集合); map .put( "collection " ,list集合); map.put( "list",list集合);
-
Array:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map. put ( " arg0",数组); map. put( " array ",数组);
- 其他类型:直接使用
-
多个参数:封装为Map集合,可以使用@Param注解,替换Map集合中默认的arg键名
map.put ("arg0",参数值1); map.put("param1",参数值1); map.put("agr1",参数值2); map.put("param2",参数值2); /设置@Param ( "username " ) map.put("username",参数值1); map.put("param1",参数值1); map.put("agr1",参数值2); map.put("param2",参数值2);
建议:将来都使用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来获取值,这样可读性更高!
注解完成增删改查使用注解开发会比配置文件开发更加方便
@Select("select * from tb_user where id = #{id}")
public User selectByld(int id);
- 查询:@Select
- 添加: @Insert
- 修改:@Update
- 删除:@Delete
提示:
-
注解完成简单功能
-
配置文件完成复杂功能
-
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java注解不仅力不从心,还会让你本就复杂的SOL语句更加是盟不堪。因此,如果你需要做一些很复杂的操作,最好用XML来映射语句。
-
选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。换句话说,永远不要拘况于一种方式。你可以很轻松的在基于注解和XML的涯句缺射舫j方式睚自由移植和切换。



