本文主要是介绍[Java]MyBatis轻松拿下,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
介绍
在业务开发过程中, 都是使用java程序完成数据库的操作, 目前最主流的技术就是MyBatis
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
- 官网: https://mybatis.org/mybatis-3/zh/index.html
- mybatis是Apache的一个开源项目iBatis, 2010年迁移到了google code 并改名为Mybatis
- 2013年11月迁移到Github
快速入门
1.使用流程
1.1准备工作
- 创建springboot工程, 勾选
- Mybatis Framework (Mybatis依赖)
- MySQL Druver (MySQL驱动依赖)
- 清理原始工程
- 准备实体类
- 用于封装查询出来的数据
- 实体类的属性名与表中的字段名一一对应。
- 实体类的属性类型建议使用包装类型
- 生成get/set方法
- 生成有参构造器和无参构造器
- 重写toString()方法
- 准备数据库表
1.2配置Mybatis
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/数据库名字
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234
1.3编写SQL语句
- 创建Mapper包, 定义持久层接口XxxMapper,
- 使用@Mapper注解标识接口;
- 作用: 把接口交给Mybatis管理
- 在运行时, mybatis会自动生成该接口的实现类对象, 并且把该对象交给IOC容器管理
- 作用: 简化数据库的操作
- 定义抽象方法, 书写SQL语句
- 通过注解执行SQL语句
1.4启动测试
@SpringBootTest //springboot整合单元测试的注解
class Day03MybatisApplicationTests {// 注入Mapper接口的实现类对象@Autowiredprivate UserMapper userMapper;@Testpublic void testListUser() {// 调用实现类对象的方法完成数据库操作List<User> userList = userMapper.list();userList.stream().forEach(user -> {System.out.println(user);});}}
2.配置提示
打开语法提示: 默认在mybatis中编写sql语句是不识别的, 可以做一些配置
关联数据库: 在IDEA和数据库默认没有建立连接, 所以不能提示表信息, 需要在idea中配置Mysql数据库信息
3.JDBC
JDBC是java语言操作关系型数据库的一套API
- sun公司官方定义的一套操作所有关系型数据可的规范, 即接口
- 各个数据库厂商去实现这套接口, 提供数据库驱动jar包
- 我们使用这套接口(JDBC)编程, 真正执行的代码是驱动jar包中的实现类
JDBC操作数据库存在的问题
- 注册驱动这块的代码存在硬编码现象
- 封装数据库数据的代码非常繁琐, 需要一条一条的封装
- 每次操作数据库都要创建和释放资源, 性能降低
- 在mybatis中, 通过配置的方式连接数据库
- 通过注解执行sql语句, 就可以完成数据库操作以及数据封装
- 通过数据库连接池, 管理数据库连接对象, 避免频繁创建和释放资源
- 使用mybatis操作数据库, 只需要配置连接信息, 编写mapper接口, 非常高效
4.数据库连接池
数据库连接池是个容器, 负责分配 管理数据库连接对象.
标准接口
- DetaSource 是官方(sun)提供的数据库连接池接口, 供第三方公司实现
- 如果想要开发连接池驱动, 就必须实现该接口
- 该接口的作用就是获取数据库连接对象
- 核心方法: Connection getConnection() thows SQLException;
- 常见产品
- Hikari(追光者)是springboot默认使用的连接池技术
- Druid(德鲁伊)是阿里巴巴开源的连接池技术, 功能强大, 性能优秀
切换连接池
- 德鲁伊官网:
- 切换到Druid连接池, 只需要引入德鲁伊连接池依赖就可以了
- 切换的效果
5.lombok
lombok的作用就是简化实体类的定义, 提高开发效率
- Lombok是一个实用的java类库,
- 通过注解的形式, 可以自动生成构造器, getter/setter. equals, hashcide, toString等方法,
- 还可以自动生成日志变量
引入
// 无需指定版本
// 因为lombok已经集成到springboot父工程中, 统一管理版本
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
注解
插件
- lombok在编译时, 会自动生成对应的java代码, 使用lombok时, 还需要安装插件
- ieda自带该插件, 较老版本的ieda可能需要手动安装
注解
通过Mybatis提供的注解, 完成数据库的增删改查操作
1.删除数据
@mapper // 把接口交给myBatis管理
public interface EmpMapper {//指定sql语句: 根据id删除数据@Delete("delete from emp where id = #{id}")public void delete(Integer id);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {// 注入empMapper对象@Autowiredprivate EmpMapper empMapper;@Testpublic void testDelete () {// 执行对象的删除方法empMapper.delete(17);}
}
- 删除操作会返回一个int类型的数值, 表示删除成功的个数, 需要的时候获取
- mybatis提供了参数占位符 #{}, 用于读取方法传递的参数
2.参数占位符
1.开启日志输出
在application.prpperties文件中开启日志输出功能, 我们就能在控制台看到mybatis执行的slq语句
#指定mybatis输出日志的位置(输出控制台)
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3.演示sql注入
SQL注入是通过操作输入的数据来修改系统的sql语句, 达到对服务器进行攻击的方法
执行jar包
// 打开cmd窗口, 定位到文件所在目录
java -jar 文件名
访问项目
// 正常访问
select count(*) from emp where username = 'zhangwuji' and posseord = '123456';
// 登录失败
select count(*) from emp where username = 'zhangwuji' and posseord = '11111';
// sql攻击
select count(*) from emp where username = 'aaass' and posseord = '' or '1' = '1';
3.预编译sql
在mybatis中, 使用 #{ ... } 占位的SQL语句, 生成的就是预编译SQL
- 当SQL真正执行时, 会自动将 #{} 内的值替换到 ? 号位置, 形成完整的语句
- 参数的传递, 都使用#{...}, 安全可靠
预编译sql拥有更好的执行性能(缓存机制) 和 更好的安全防护(sql注入)
- 拼接sql: 每次执行的sql语句都是不同的, 所以无法命中缓存中的sql语句
- 动态sql: 每次执行的sql语句都是相同的, 可以命中缓存中的sql语句, 在执行阶段拼接具体的值
4.拼接SQL
在mybatis中, 使用 #${ ... } 占位的SQL语句, 生成的就是拼接SQL
- 直接将参数拼接在SQL语句中, 一般很少使用
- 如果对表名, 列表进行动态设置时使用
4.新增数据
@mapper // 把接口交给myBatis管理
public interface EmpMapper {// 开启主键返回, 并指定将主键值赋值给实体类的id属性@Options(useGeneratedKeys = true, keyProperty = "id")//指定sql语句: 新增员工@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")public void insert(Emp emp);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {// 注入empMapper对象@Autowiredprivate EmpMapper empMapper;@Testpublic void testDelete () {// 构建员工对象Emp emp = new Enm();// 为对象添加数据emp.setUsername("Tom");emp.setName("汤姆");emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2000,1,1));emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);// 执行对象的新增方法empMapper.insert(emp);// 如果开启了主键返回, 就可以拿到新增数据的id主键值System.out.printIn(emp.getId());}
}
- 主键返回: 新增操作默认不会返回主键的值, 如果需要主键值时, 通过添加注解开启
- 开启主键返回后, 新增操作完成, 可以通过实体类, 拿到新增数据的id主键值
5.修改数据
@mapper // 把接口交给myBatis管理
public interface EmpMapper {//指定sql语句: 更新员工@Update("update emp set username = #{username},name=#{name},gender = #{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id =#{id};")public void update(Emp emp);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {// 注入empMapper对象@Autowiredprivate EmpMapper empMapper;@Testpublic void testDelete () {// 构建员工对象Emp emp = new Enm();// 为对象添加数据emp.setUsername("Tom");emp.setId(18);emp.setName("汤姆");emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2000,1,1));emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);// 执行对象的更新方法empMapper.update(emp);}
}
6.数据封装
实体类属性名 和 数据库表的字段名一致, Mybatis会自动封装
实体类属性名 和 数据库表的字段名不一致, 不能自动封装
- 通过查询语句查到数据, 把数据封装到实体中, 返回给前端
- 由于实体类采用驼峰命名法, 数据库中采用下划线分割, 会导致有些数据无法自动封装
1.起别名
在SQL语句中, 给不一样的字段名设置一个别名, 别名和实体类的属性名一致, 就可以正确封装数据
2.手动结果映射
通过@Results 和 @Result 注解, 手动对映射结果进行调整, 以正确的封装数据
3.开启驼峰命名转换
让Mybatis自动把 下划线的字段名 转成 驼峰命名风格, 以完成封装数据
#开启mubatis驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
7.查询数据
@mapper // 把接口交给myBatis管理
public interface EmpMapper {//指定sql语句: 根据id查询员工@Select("select * from emp where id= #{id}")public Emp getById(Integer id);
}
@mapper // 把接口交给myBatis管理
public interface EmpMapper {//指定sql语句: 根据条件查询员工@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +"entrydate between #{begin} and #{end} order by update_time desc;")public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisCrudApplicationTests {// 注入empMapper对象@Autowiredprivate EmpMapper empMapper;@Testpublic void testGetById () { // 执行对象的查询方法Emp emp = empMapper.getById(1);System.out.printIn(emp);}@Testpublic void testList () { // 执行对象的条件查询方法List<Emp> list = empMapper.list("张", (short) 1, LocalDate.of(2010,1,1), LocalDate.of(2020,1,1));System.out.printIn(list);}
}
- #{}不能在引号内使用, ${}可以在引号内使用, 但是不推荐使用
- 建议使用mysql提供的 concat() 拼接函数, 用于拼接字符串
- concat('hello', 'Mysql' ,'!!!') 执行结果是 'helloMysql!!!'
8.版本差异
在早期或者单独使用mybatis时, 需要使用 @Param()注解 声明形参, 才能在 #{} 中使用数据, 原因是spinrgboot2.x版本 中引用了一个插件, 可以在编码后记住形参的名字, 有名字才能正确的访问数据
XML
使用mybatis的注解, 主要用来完成简单的增删改查, 如果是复杂的sql, 建议使用 xml 文件来映射sql语句
1,创建xml文件
XML映射文件的名称与Mapper接口名称一致,并且XML文件和Mapper接口放置在相同包下(同包同名)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="待定"></mapper>
2,设置namespace属性
XML映射文件的namespace属性为Mapper接口全限定名一致
复制接口全类名:
<mapper namespace="com.itheima.mapper.EmpMapper">
</mapper>
3.编写sql, 设置id属性
XML映射文件中, sql语句的id 与Mapper文件中的方法名一致, 并保持返回类型一致
<mapper namespace="com.itheima.mapper.EmpMapper">// resultType: 单条记录所封装的类型(指定返回值的类型)// id="xx": id与mapper文件的方法名一致<select id="list" resultType="com.itheima.pojo.Emp">select * from emp where name like concat('%',#{name},'%') and gender = #{gender} andentrydate between #{begin} and #{end} order by update_time desc;</select></mapper>
4.插件
MybatisX是一款基于IDEA的快速开发Mabatis的插件, 为效率而生
生成XML文件中的sql标签
- alt +enter -> Generate statement -> 自动生成SQL语句
- ctrl +alt + L : 格式化sql语句
动态SQL
随着条件变化而变化的SQL语句称为动态sql
if标签
用于判断条件是否成立, 使用test属性进行条件判断, 如果条件为true, 则拼接SQL,
需求: 根据条件查询员工, 筛选字段有值, 则作为条件, 没有值则忽略
<select id="list" resultType="com.itheima.pojo.Emp">select * from empwhere <if test="name != null">name like concat('%', #{name}, '%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if>order by update_time desc
</select>
- 以上代码通过 if标签 实现了条件的动态拼接
- 但是代码存在问题, 不传name, 只根据gender查询, sql语句中就会多出一个 and关键字
- 所以在书写动态sql时, 会使用where标签 替换 where关键字
where元素只会在 子元素有内容 的情况下才插入where子句, 而且会自动去除子句 多余的AND 或 OR
<select id="list" resultType="com.itheima.pojo.Emp">select * from emp<where><if test="name != null">name like concat('%',#{name},'%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time desc
</select>
动态的在行首插入 SET 关键字, 并会删除多余的逗号, 用在update语句中
需求: 动态更新员工数据, 如果更新时传递有值,则更新该字段, 否则不更新
<update id="update">update emp<set><if test="username != null">username = #{username},</if><if test="name != null">name = #{name},</if><if test="gender != null">gender = #{gemder},</if><if test="job != null">job = #{job},</if><if test="updateTime != null">update_time = #{updateTime}</if></set>where id = #{id}
</select>
- 如果不使用set标签替换set关键字, 代码就会有问题
- 比如只传入username字段, 后面的字段不传, sql语句中就会多出一个逗号
- 所以在动态更新数据时, 会使用set标签替换set关键字
foreach标签
循环遍历, 主要用在批量操作中
// 批量删除员工
public void deleteByIds(List<Integer> ids);
// 批量删除员工(18,19,20)
<delete id="deleteById">delete from emp where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach>
</delete>
sql标签
封装重复性的SQL语句
<mapper namespace="com.itheima.mapper.EmpMapper">// 定义可重用的sql片段<sql id="唯一名称">select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_timefrom emp</sql><select id="list" resultType="com.itheima.pojo.Emp">// 通过refid属性, 引入sql片段<include refid = "唯一名称" />where <if test="name != null">name like concat('%', #{name}, '%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if>order by update_time desc</select>
</mapper>
这篇关于[Java]MyBatis轻松拿下的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!