springboot3.0整合mybatis
分类: springboot 专栏: springboot3.0新教材 标签: 整合mybatis
2023-12-28 17:14:01 1325浏览
前期回顾
- 什么是浏览器同源策略?
- 跨域有几种解决方案
- 全局统一异常处理用什么注解?
- thymeleaf模板技术常用表达式说几个
- swagger是什么技术?有什么作用和优势?
使用注解查询
核心流程:
以下这张表作为演示案例
1.加依赖
切记:springboot版本是3.0.0的话,mybatis的版本必须是3.0.3
不过:如果你项目中用了swagger,那springboot版本用2.7.1,mybatis版本用2.1.2
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其中mybatis-spring-boot-starter是重点,是MyBatis官方提供的整合包。
2.application.properties
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///bookstore?characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
其中type表示使用Druid连接池数据源,如果不配置,则使用默认的连接池Hikari
book实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private String name;
private Double price;
private String category;
private Integer pnum;
private String imgurl;
private String description;
private String author;
private Integer sales;
}
3.mapper接口
@Mapper
public interface BookMapper {
@Select("select * from book")
public List<Book> findAllBooks(); //查询所有书
@Select("select * from book where id=#{id}")
public Book findBookById(int id); //根据id号查找一本书
@Insert("insert into book values(null,#{name},#{price},#{category},#{pnum},#{imgurl},#{description},#{author},#{sales})")
public void addBook(Book book); //添加一本书
@Update("update book set name=#{name},price=#{price},category=#{category}, " +
"pnum=${pnum},imgurl=#{imgurl},description=#{description}," +
"author=#{author},sales=#{sales} where id=#{id}")
public void updateBook(Book book); //修改一本书
@Delete("delete from book where id=#{id}")
public void deleteBook(int id); //删除一本书
}
MyBatis项目的所有数据访问层接口都要添加@Mapper注解,也可以都不添加,但要在Spring Boot入口类中添加@MapperScan("包名")注解,这样会自动扫描所有该包下的接口。
4.前端页面核心代码
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>图书信息列表</title>
</head>
<body>
<a th:href="@{/addBook}">添加新书</a>
<table border="1" align="center">
<tr>
<td>编号</td>
<td>书名</td>
<td>价格</td>
<td>类目</td>
<td>库存</td>
<td>图片</td>
<td>说明</td>
<td>作者</td>
<td>已售</td>
</tr>
<tr th:each="book:${books}">
<td th:text="${book.id}"></td>
<td th:text="${book.name}"></td>
<td th:text="${book.price}"></td>
<td th:text="${book.category}"></td>
<td th:text="${book.pnum}"></td>
<td th:text="${book.imgurl}"></td>
<td th:text="${book.description}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.sales}"></td>
</tr>
</table>
</body>
</html>
5.效果
动态查询
@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider注解实现动态增删改查。下面以@SelectProvider注解为例进行说明。
1.添加@SelectProvider注解
@SelectProvider(method = "searchBookSql",type = SqlContext.class) //动态查询
public List<Book> searchBooks(Book book);
2.动态sql类
上述代码的@SelectProvider注解中type属性表示要调用的类,method属性表示需要调用上述类中的方法名称,该方法用于创建动态的SQL查询语句。在同一个包下创建类SqlContext,创建方法searchBookSql。
public class SqlContext {
//构造动态查询图书的SQL语句
public String searchBookSql(Book book){
return new SQL(){
{ SELECT("*");
FROM("book");
if(book.getName()!=null&&book.getName()!=""){
WHERE(" name like '%' #{name} '%'");
}
if(book.getCategory()!=null&&book.getCategory()!=""){
WHERE(" category=#{category}");
}
if(book.getAuthor()!=null&&book.getAuthor()!=""){
WHERE(" author=#{author}");
}
}
}.toString();
}
}
其余步骤就是常规操作,service和controller的写法跟之前一样。
3.补充-动态sql的另一种写法
@Mapper
public interface EtStuMapper {
@Select("select * from et_stu where id = #{0}")
public EtStu getById(String id);
@Insert("insert into et_stu (upass,realname,stu_no,sex,sys_id,major_id) values (#{upass},#{realname},#{stu_no},#{sex},#{sys_id},#{major_id}) ")
public void insert(EtStu o);
@Update("<script>update et_stu "
+"<trim prefix=\"set\" suffixOverrides=\",\">"
+"<if test=\"realname != null and realname != ''\">realname = #{realname},</if>"
+"<if test=\"stu_no != null and stu_no != ''\">stu_no = #{stu_no},</if>"
+"<if test=\"sex != null and sex != ''\">sex = #{sex},</if>"
+"<if test=\"upass != null and upass != ''\">upass = #{upass},</if>"
+"<if test=\"sys_id != null and sys_id != ''\">sys_id = #{sys_id},</if>"
+"<if test=\"major_id != null and major_id != ''\">major_id = #{major_id},</if>"
+"</trim> where id=#{id}</script>")
public void update(EtStu o);
@Select("<script>select s.*,y.sys_name,m.major_name from et_stu s left join et_system y on y.id=s.sys_id "
+ "left join et_major m on m.id=s.major_id where 1=1"
+"<if test=\"realname != null and realname !='' \"> and realname like concat('%',#{realname},'%') </if>"
+"<if test=\"stu_no != null and stu_no !='' \"> and stu_no = #{stu_no} </if>"
+"<if test=\"sys_id != null and sys_id !='' \"> and sys_id = #{sys_id} </if>"
+"<if test=\"major_id != null and major_id !='' \"> and major_id = #{major_id} </if>"
+"<if test=\"upass != null and upass !='' \"> and upass = #{upass} </if>"
+"</script>")
public List<EtStu> list(EtStu o);
@Delete("delete from et_stu where id = #{0}")
public void delete(String id);
}
分页查询
1.导入依赖
<!--pagehelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
2.配置分页属性
pagehelper:
helper-dialect: mysql #指明当前查询的是MySQL数据库
reasonable: true #启用合理化,当pageNum小于1时查询第1页,当pageNum大于页数时查询最后一页
support-methods-arguments: true #是否自动分页,依据的是入参,如果参数中有pageNum,pageSize分页参数,则会自动分页
params: count=countSql #如果POJO或者Map中发现了countSql属性,就作为count参数使用
3.后端分页核心代码
@GetMapping("/booksPage")
public ModelAndView booksPage(@RequestParam(value="start",defaultValue = "1")int start,
@RequestParam(value="size",defaultValue = "3") int size){ //默认查询第1页,每页显示3条
PageHelper.startPage(start,size,"id asc"); //表示起始页为start每页显示size条根据id升序排序进行分页
List<Book> books=bookService.findAllBooks();
PageInfo<Book> page=new PageInfo<>(books);
ModelAndView mv=new ModelAndView();
mv.addObject("page",page);
mv.setViewName("bookslistPage");
return mv;
}
4.前端分页核心代码
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>图书信息列表</title>
</head>
<body>
<table border="1" align="center">
<tr>
<td>编号</td>
<td>书名</td>
<td>库存</td>
<td>价格</td>
<td>类目</td>
<td>说明</td>
<td>图片</td>
<td>作者</td>
<td>已售</td>
</tr>
<tr th:each="book:${page.list}">
<td th:text="${book.id}"></td>
<td th:text="${book.name}"></td>
<td th:text="${book.pnum}"></td>
<td th:text="${book.price}"></td>
<td th:text="${book.category}"></td>
<td th:text="${book.description}"></td>
<td th:text="${book.imgurl}"></td>
<td th:text="${book.author}"></td>
<td th:text="${book.sales}"></td>
</tr>
</table>
<br/>
总页数:<span th:text="${page.pages}"></span>
总记录数:<span th:text="${page.total}"></span>
页面尺寸:<span th:text="${page.pageSize}"></span>
当前页记录数:<span th:text="${page.size}"></span>
<span th:if="${page.hasPreviousPage}">
<a th:href="@{/book/page(pageNum=${page.pageNum-1})}">上一页</a>
</span>
<span th:each="p:${#numbers.sequence(1,page.pages)}">
<a th:href="@{/book/page(pageNum=${p})}" th:text="${p}"></a>
</span>
<span th:if="${page.hasNextPage}">
<a th:href="@{/book/page(pageNum=${page.pageNum+1})}">下一页</a>
</span>
</body>
</html>
5.效果
使用XML映射文件查询
使用注解的方式进行单表的查询非常方便,但多表查询,结果映射等复杂应用情形仍然推荐使用XML映射文件的方式进行查询。
mybatis:
type-aliases-package: com.jf3q.mybatis.entity #扫描别名包
mapper-locations: classpath:mappers/*.xml #加载此路径下的映射文件
具体写法,咱们在ssm阶段已经学习过了,这里就不赘述了
备注:另外就是把sql映射文件直接放到跟dao接口同一目录下,编译后sql映射文件没打进去,需要修改一下pom.xml文件
<build>
<finalName>boot-mybatis</finalName>
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
动态更新
用xml的方式操作最简单,ssm写过了
批量删除
使用MyBatis的<foreach>循环,也是用XML映射文件来处理
<delete id="deleteBooks">
delete from book where id in
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
页面上怎么写??
提示:复选框
书上的写法
<input type="button" value="删除所选" onclick="dels()"/>
function dels() {
if (confirm("你确定要删除所选吗")) {
var ids = "";
$(".ids").each(function (i, e) {
if ($(e).is(":checked")) {
var id = $(e).val();
ids += id + ",";
}
});
if (ids.length == 0) {
alert("请选择删除项!");
} else {
// alert(ids);
//去除最后一个,号
ids = ids.substr(0, ids.length - 1);
location.href = "deleteBooks?id=" + ids;//构造出类似deleteBooks?id=1,2,3这样的URL,后台可用数组接收
}
}
}
有没有好的想法?
用form表单的形式提交行不行?思考下
<form th:action="@{/book}" method="post" onsubmit="return submitForm()">
<tr th:each="book:${page.list}">
<td >
<input type="checkbox" name="ids" th:value="${book.id}">
</td>
……
<input type="submit" value="删除" onsubmit="return submitForm()">
</form>
<script src="/js/jquery-3.1.0.min.js"></script>
<script>
function submitForm() {
if ($("input[name='ids']:checked").length == 0) {
alert("必须选择一个记录删除")
return false
}
if (confirm("确定要删除吗?")) {
}else{
alert("已取消删除")
return false
}
}
</script>
一对多关联查询
以班级为主表,一个班级下有多个学生
有两种方案:
1两表连查
2.子查询的方式
多对一关联查询
以学生为主表,多个学生对应一个班级
也是有两种方案
1.两表联查的方式
2.子查询的方式
自连接查询
多对一自连接查询
员工表employee中每个员工,包括经理都有个编号,每个员工都有对应的上司的员工编号(老板除外),查询某个编号的员工信息及其对应的上司信息。由于上司也是同一个表中的员工,所以这属于自连接查询。
1.实体类加属性
2.sql映射文件
一对多自连接查询
员工表employee中每个员工,包括经理都有个编号,每个员工都有对应的上司的员工编号(老板除外),查询某个编号的员工信息及其所有的下属信息
1.修改实体类
2.sql映射
不等连接查询
查询各个员工的信息及其工资等级。
1.数据库准备。新建一个工资等级表salarylevel
2.修改实体类Employee。在实体类Employee中添加一个表示工资等级的属性
3.sql映射文件
这个就是不等连接的重点,这里两表连接查询条件不再是外键相等,而是一个范围。
作业
1.将掌上游戏app项目改成springboot整合mybatis的架构
2.把书籍demo完善增删改查
在此基础上继续完善。
好博客就要一起分享哦!分享海报
此处可发布评论
评论(0)展开评论
展开评论