用discuz做的门户网站,数据可视化网站,wordpress genesis,dux wordpressWeb后端开发_03
MyBatis框架
什么是MyBatis? MyBatis是一款优秀的持久层框架#xff0c;用于简化JDBC的开发。MyBatis本是 Apache的一个开源项目iBatis#xff0c;2010年这个项目由apache迁移到了google code#xff0c;并且改名为MyBatis 。2013年11月迁移到Github。官网…Web后端开发_03
MyBatis框架
什么是MyBatis? MyBatis是一款优秀的持久层框架用于简化JDBC的开发。MyBatis本是 Apache的一个开源项目iBatis2010年这个项目由apache迁移到了google code并且改名为MyBatis 。2013年11月迁移到Github。官网https://mybatis.org/mybatis-3/zh/index.html
MyBatis入门
快速入门
使用MyBatis查询所有用户数据
准备工作创建springboot工程、数据库表user、实体类User引入Mybatis相关依赖配置Mybatis数据库连接信息编写SQL语句注解/XML 数据准备
create table user
(id int unsigned primary key auto_increment comment ID,name varchar(100) comment 姓名,age tinyint unsigned comment 年龄,gender tinyint unsigned comment 性别, 1:男, 2:女,phone varchar(11) comment 手机号
) comment 用户表;insert into user(id, name, age, gender, phone)
VALUES (null, 白眉鹰王, 55, 1, 18800000000);
insert into user(id, name, age, gender, phone)
VALUES (null, 金毛狮王, 45, 1, 18800000001);
insert into user(id, name, age, gender, phone)
VALUES (null, 青翼蝠王, 38, 1, 18800000002);
insert into user(id, name, age, gender, phone)
VALUES (null, 紫衫龙王, 42, 2, 18800000003);
insert into user(id, name, age, gender, phone)
VALUES (null, 光明左使, 37, 1, 18800000004);
insert into user(id, name, age, gender, phone)
VALUES (null, 光明右使, 48, 1, 18800000005);创建springboot项目 选择依赖MyBatis FrameworkMySQL Driver 配置数据库连接信息
#驱动类名称
spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.urljdbc:mysql://127.0.0.1:3306/mybatis
#连接数据库的用户名
spring.datasource.usernameroot
#连接数据库的密码
spring.datasource.password123456编写SQL语句
Mapper //在运行时会自动生成该接口的实现类对象代理对象并且将该对象交给IOC容器管理
public interface UserMapper {//查询全部的用户信息Select(select * from user)public ListUser list();
}单元测试
SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisQuickstartApplicationTests {Autowiredprivate UserMapper userMapper;Testpublic void testListUser() {ListUser userList userMapper.list();userList.stream().forEach(user - {System.out.println(user);});}
}测试结果 默认在MyBatis中编写SQL语句是不识别的。可以做如下配置 配置SQL提示
产生原因IDEA和数据库没有建立连接不识别表信息、解决方式在IDEA中配置MySQL数据库连接 JDBC介绍
JDBCJava DataBase Connectivity就是使用Java语言操作关系型数据库的一套API。 例如 dependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependency本质 sun公司官方定义的一套操作所有关系型数据库的规范即接口。各个数据库厂商去实现这套接口提供数据库驱动jar包。我们可以直接使用这套接口JDBC编程真正执行的代码是驱动jar包中的实现类。 JDBC缺点 MyBatis优势 数据库连接池 数据库连接池 数据库连接池是个容器负责分配、管理数据库连接Connection它允许应用程序重复使用一个现有的数据库连接再不是在建立一个释放空闲时间超过最大空闲时间的连接来避免因为没有释放连接而引起的数据库连接遗漏 优势 资源复用提升系统响应速度避免数据库连接遗漏 标准接口DataSource 官方提供的数据库连接池接口由第三方组织实现此接口。功能获取连接 Connection getConnection() throws SQLException;常见产品 Druid德鲁伊 Druid连接池是阿里巴巴开源数据库连接池项目功能强大性能优秀是Java语言最好的数据库连接池之一 切换Druid数据库连接池 官方地址https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.2.8/version
/dependencylombok Lombok是一个实用的Java类库能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法并可以自动化生成日志变量简化Java开发、提高效率。 引入lombok依赖
dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId
/dependency示例
Data
NoArgsConstructor//无参构造
AllArgsConstructor//有参构造
public class User {private Integer id;private String name;private Short age;private Short gender;private String phone;
}注意事项 Lombok会在编译时自动生成对应的java代码。使用lombok时还需要安装一个lombok的插件IDEA自带。 MyBatis基础增删改查
需求说明
根据资料中提供的《tlias智能学习辅助系统》页面原型及需求完成员工管理的需求开发。 准备
准备工作
准备数据库emp创建一个新的springboot工程选择引入对应的起步依赖mybatis、mysql驱动、lombokapplication.properties中引入数据库连接信息创建对应的实体类Emp实体类属性采用驼峰命名法准备Mapper接口EmpMapper
准备数据库emp
-- 员工管理
create table emp
(id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32) default 123456 comment 密码,name varchar(10) not null comment 姓名,gender tinyint unsigned not null comment 性别, 说明: 1 男, 2 女,image varchar(300) comment 图像,job tinyint unsigned comment 职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师,entrydate date comment 入职时间,dept_id int unsigned comment 部门ID,create_time datetime not null comment 创建时间,update_time datetime not null comment 修改时间
) comment 员工表;INSERT INTO emp
(id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
VALUES (1, jinyong, 123456, 金庸, 1, 1.jpg, 4, 2000-01-01, 2, now(), now()),(2, zhangwuji, 123456, 张无忌, 1, 2.jpg, 2, 2015-01-01, 2, now(), now()),(3, yangxiao, 123456, 杨逍, 1, 3.jpg, 2, 2008-05-01, 2, now(), now()),(4, weiyixiao, 123456, 韦一笑, 1, 4.jpg, 2, 2007-01-01, 2, now(), now()),(5, changyuchun, 123456, 常遇春, 1, 5.jpg, 2, 2012-12-05, 2, now(), now()),(6, xiaozhao, 123456, 小昭, 2, 6.jpg, 3, 2013-09-05, 1, now(), now()),(7, jixiaofu, 123456, 纪晓芙, 2, 7.jpg, 1, 2005-08-01, 1, now(), now()),(8, zhouzhiruo, 123456, 周芷若, 2, 8.jpg, 1, 2014-11-09, 1, now(), now()),(9, dingminjun, 123456, 丁敏君, 2, 9.jpg, 1, 2011-03-11, 1, now(), now()),(10, zhaomin, 123456, 赵敏, 2, 10.jpg, 1, 2013-09-05, 1, now(), now()),(11, luzhangke, 123456, 鹿杖客, 1, 11.jpg, 5, 2007-02-01, 3, now(), now()),(12, hebiweng, 123456, 鹤笔翁, 1, 12.jpg, 5, 2008-08-18, 3, now(), now()),(13, fangdongbai, 123456, 方东白, 1, 13.jpg, 5, 2012-11-01, 3, now(), now()),(14, zhangsanfeng, 123456, 张三丰, 1, 14.jpg, 2, 2002-08-01, 2, now(), now()),(15, yulianzhou, 123456, 俞莲舟, 1, 15.jpg, 2, 2011-05-01, 2, now(), now()),(16, songyuanqiao, 123456, 宋远桥, 1, 16.jpg, 2, 2010-01-01, 2, now(), now()),(17, chenyouliang, 123456, 陈友谅, 1, 17.jpg, NULL, 2015-03-21, NULL, now(), now());删除
根据主键删除 SQL语句
delete from emp where id 17;接口方法 Delete(delete from emp where id #{id})
public void delete(Integer id);注意事项 如果mapper接口方法形参只有一个普通类型的参数#{...}里面的属性名可以随便编写如#{id}、#{value}。 日志输出 可以在application.properties中打开mybatis的日志并指定输出到控制台。 #指定mybatis输出日志的位置输出控制台
mybatis.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl预编译SQL 优势 性能更高更安全防止SQL注入 SQL注入
SQL注入是通过操作输入的数据来修改事先定义好的SQL语句以达到执行代码对服务器进行攻击的方法。
参数占位符 #{...} 执行SQL时会将#{...}替换为?生成预编译SQL会自动设置参数值使用时机参数传递时都用#{...} ${...} 拼接SQL。直接将参数拼接在SQL语句中存在SQL注入问题使用时机如果对表名、列表进行动态设置时使用 插入新增
新增 SQL语句 insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
values (Tom, 汤姆, 1, 1.jpg, 1, 2000-05-05, 1, now(), now());接口方法 Mapper
public interface EmpMapper {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
class SpringbootMybatisCrudApplicationTests {Autowiredprivate EmpMapper empMapper;Testpublic void testInsert() {//构造员工对象Emp emp new Emp();emp.setUsername(Tom);emp.setName(汤姆);emp.setImage(1.jpg);emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2000, 1, 4));emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);//执行新增员工信息操作empMapper.insert(emp);}
}新增主键返回
描述在数据添加成功后需要获取插入数据库数据的主键。如添加套餐数据时还需要维护套餐菜品关系表数据。 实现 Mapper
public interface EmpMapper {Options(useGeneratedKeys true,keyProperty id)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);
}Options(useGeneratedKeys true,keyProperty id)会自动将生成的主键值赋值给emp对象的id属性
更新 SQL语句根据ID更新员工信息 update emp set usernamezhaomin, name赵敏, gender2, image5.jpg, job2,entrydate2008-12-18, dept_id1, update_time2023-11-25 12:38:20 where id 18;接口方法 Mapper
public interface EmpMapper {Options(useGeneratedKeys true,keyProperty id)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
class SpringbootMybatisCrudApplicationTests {Autowiredprivate EmpMapper empMapper;Testpublic void testUpdate() {//构造员工对象Emp emp new Emp();emp.setId(18);emp.setUsername(Tom5);emp.setName(汤姆5);emp.setImage(1.jpg);emp.setGender((short) 1);emp.setJob((short) 1);emp.setEntrydate(LocalDate.of(2002, 1, 9));emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);//执行更新员工信息操作empMapper.update(emp);}
}查询
根据ID查询
用于页面的回显展示 SQL语句 select * from emp where id 2;接口方法 Mapper
public interface EmpMapper {Options(useGeneratedKeys true,keyProperty id)Select(select * from emp where id #{id})public Emp getByID(Integer id);
}测试查询 SpringBootTest
class SpringbootMybatisCrudApplicationTests {Autowiredprivate EmpMapper empMapper;Testpublic void testGetById() {Emp emp empMapper.getByID(5);System.out.println(emp);}
}查询结果 Emp(id5, usernamechangyuchun, password123456, name常遇春, gender1, image5.jpg, job2, entrydate2012-12-05, deptIdnull, createTimenull, updateTimenull)数据封装
实体类属性名和数据库表查询返回的字段名一致mybatis会自动封装如果实体类属性名和数据库表查询返回的字段名不一致mybatis不会自动封装 解决方案 起别名在SQL语句中对不一样的列名起别名别名和实体类属性名一样 Select(select id, username, password, name, gender, image, job, entrydate, dept_id deptId, create_time createTime, update_time updateTime from emp where id #{id})
public Emp getByID(Integer id);手动映射结果通过Results及Result进行手动结果映射 Select(select * from emp where id #{id})
Results({Result(column dept_id, property deptId),Result(column create_time, property createTime),Result(column update_time, property updateTime)
})
public Emp getByID(Integer id);开启驼峰命名如果字段名与属性名符合驼峰命名规则mybatis会自动通过驼峰命名规则映射 #开启驼峰命名自动映射即从数据库字段名a_column映射到java属性名aColumn.
mybatis.configuration.map-underscore-to-camel-casetrue条件查询 SQL语句 -- 模糊查询
select * from emp where name like %张% and gender 1 and entrydate between 2010-01-01 and 2020-01-01 order by update_time desc ;
-- 使用concat()
select * from emp where name like concat(%, 张, %) and gender 1 and entrydate between 2010-01-01 and 2020-01-01 order by update_time desc ;接口方法 1、以下方法性能低、不安全、存在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 ListEmp list(Param(name) String name, Param(gender) Short gender,Param(begin) LocalDate begin, Param(end) LocalDate end);2、推荐使用下列方法 Select(select * from emp where name like concat(%,#{name},%) and gender #{gender} and entrydate between #{begin} and #{end} order by update_time desc )
public ListEmp list(Param(name) String name, Param(gender) Short gender,Param(begin) LocalDate begin, Param(end) LocalDate end);
参数名说明 在springboot2.x版本 Select(select * from emp where name like concat(%,#{name},%) and gender #{gender} and entrydate between #{begin} and #{end} order by update_time desc )
public ListEmp list(String name, Short gender, LocalDate begin, LocalDate end);在springboot1.x版本/单独使用mybatis Select(select * from emp where name like concat(%,#{name},%) and gender #{gender} and entrydate between #{begin} and #{end} order by update_time desc )
public ListEmp list(Param(name) String name, Param(gender) Short gender,Param(begin) LocalDate begin, Param(end) LocalDate end);XML映射文件 规范 XML映射文件的名称与Mapper接口名称一致并且将XML映射文件和Mapper接口放置在相同包下**同包同名**XML映射文件的namespace属性为Mapper接口全限定名一致XML映射文件中SQL语句的id与Mapper接口中的方法名一致并保持返回类型一致 MybatisX是一款基于IDEA的快速开发Mybatis的插件为效率而生。 安装 使用注解来映射简单语句会使代码显得更加简洁但对于稍微复杂一点的语句Java 注解不仅力不从心还会让你本就复杂的 SQL 语句更加混乱不堪。 因此如果你需要做一些很复杂的操作最好用 XML 来映射语句。 选择何种方式来配置映射以及认为是否应该要统一映射语句定义的形式完全取决于你和你的团队。 换句话说永远不要拘泥于一种方式你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。 使用Mybatis的注解主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能建议使用XML来配置映射语句
官方说明https://mybatis.net.cn/getting-started.html
MyBatis动态SQL
动态SQL
随着用户的输入或外部条件的变化而变化的SQL语句称为动态SQL。 if if:用于判断条件是否成立。使用test属性进行条件判断如果条件为true则拼接SQL。 if testname ! nullname like concat(%,#{name},%)
/ifwhere/where用来替换where关键字并且可以去除多余的and或or
案例完善更新员工功能修改为动态更新员工数据信息 需求 动态更新员工信息如果更新时传递有值则更新如果更新时没有传递值则不更新。 解决方案 动态SQLset/set用来替换set关键字并且会去除字段之后多余的,用在update语句中 小结
1、if 用于判断条件是否成立如果条件为true则拼接SQL 形式 if testname ! null.../if2、where
where元素只会在子元素有内容的情况下才插入where子句而且会自动去除子句的开头的AND或OR
3、set
动态地在行首插入SET关键字并会删除掉额外的逗号。用在update语句中
foreach主要用于批量操作中
完成批量删除操作 报错解决
Caused by: org.apache.ibatis.binding.BindingException: Parameter ids not found. Available parameters are [arg0, collection, list]解决方案参考参数名说明
EmpMapper.java中的配置文件添加Param(ids)
public void deleteByIds(Param(ids) ListInteger ids);SQL语句 delete from emp where id in (18, 19, 20);接口方法 //批量删除员工
public void deleteByIds(Param(ids) ListInteger ids);XML映射文件 !--批量删除员工(18, 19, 20)--
!--collection 遍历的集合item 遍历出来的元素separator 分隔符open 遍历开始前拼接的SQL片段close 遍历开始后拼接的SQL片段
--
delete iddeleteByIdsdelete from emp where id inforeach collectionids itemid separator, open( close)#{id}/foreach
/deletesql和include
问题分析 sql定义可重用的SQL片段即负责公共SQL片段的抽取include通过属性refid指定包含的SQL片段即负责对抽取的SQL片段进行引用 m emp where id in (18, 19, 20); - 接口方法java
//批量删除员工
public void deleteByIds(Param(ids) ListInteger ids);XML映射文件 !--批量删除员工(18, 19, 20)--
!--collection 遍历的集合item 遍历出来的元素separator 分隔符open 遍历开始前拼接的SQL片段close 遍历开始后拼接的SQL片段
--
delete iddeleteByIdsdelete from emp where id inforeach collectionids itemid separator, open( close)#{id}/foreach
/deletesql和include
问题分析
[外链图片转存中…(img-T6ISOjWb-1700927686726)] sql定义可重用的SQL片段即负责公共SQL片段的抽取include通过属性refid指定包含的SQL片段即负责对抽取的SQL片段进行引用 [外链图片转存中…(img-f7SPmrEh-1700927686726)]