Mybatis-Plus
1.1Mybatis介绍
1.1.1Mybatis缺点
1.无论做什么样的操作,所有的sql语句都必须自己手写.
2.Mybatis在进行数据库操作时依然采用"面向过程"的操作方式. 取值操作.
1.2ORM思想
1.2.1ORM介绍
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示着额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。
总结:以面向对象的方式来操作数据库.
1.2.2ORM相关说明
知识回顾: 入库操作
sql: insert into 表名(字段名称....) values (属性的值........) 面向过程的操作.
sql:select * from xxxx where xxx=xxx;
数据库操作升级版
1.update操作(更新操作 增/删/改)
xxxxMapper.insert(user); 参数传递对象即可.代码写到此 结束了.
xxxxMapper.update(user);
2.查询操作
xxxxMapper.select(参数); 需要自动的完成封装
1.3ORM具体实现思路
1.3.1需求说明
用户只需要写xxxMapper.insert(user)操作,则可以自动的实现数据库操作.
提示:
1.需要编辑公共API进行实现
2.深入的解读什么是ORM
3.mysql能否识别java中的user对象?? 只能识别sql语句 如何将对象转化为Sql
实现思路:
1.编辑共同的API 定义单表操作的全部方法!!!! 如果用户需要使用则继承即可.
2.
对象与表完成一一映射. 利用自定义的注解标识对象所映射的表.
对象中的属性与表中的字段一一映射. 可以利用自定义的注解完成映射.
3. 需要编辑底层代码,能够自动的将方法 按照指定的规则完成sql语句的转化.
LG: xxxMapper.insert(user)
SQL: insert into 表名(表中的字段) values (对象中的属性值).
最终将动态生成的Sql交给mybatis或者JDBC去处理.
常识: JDBC操作数据库是最快的.
1.4Mybatis-Plus介绍
1.4.1MP介绍
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
1.4.2特性
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
-
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
-
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
-
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
-
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
-
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
-
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
-
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
-
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
-
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
-
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
1.5Mybatis-plus入门案例
1.5.1导入jar包
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
1.5.2编辑POJO
//生成get/set/toString/equals
(chain=true)//表示链式加载 重写set方法,将对象返回
//添加无参构造 为以后框架的使用做准备
//全部参数的构造方法.
//(value="user")//定义对象与表映射关系 编辑表名
//如果表名与对象的名称一致,则可以省略不写.
public class User {
(type=IdType.AUTO)//标识主键 主键自增.
private Integer id;
//@TableField(value="name")//如果字段的名称与属性名称一致(包含驼峰规则),则可以省略
private String name;//字段与属性一一映射
private Integer age;//user_name userName
private String sex;
}
1.5.3继承公共的接口
//该接口需要交给Spring容器管理
//BaseMapper中的泛型标识操作的具体的表 千万不要写错.
public interface UserMapper extends BaseMapper<User>{
//准备查询全部用户信息的方法
List<User> findAll();
}
1.5.4编辑YML配置文件
server:
port: 8090 #表示端口号信息
servlet:
context-path: / #项目发布路径
spring:
datasource:
#如果使用高版本驱动则配置如下
#driver-class-name: com.cj.mysql.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#mybatis-plush配置 mp比mybatis功能更加强大 引用一个即可
mybatis-plus:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml #动态的导入xml映射文件
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true #为了user_id与userId完美映射.无需手动转化
1.5.5注意事项
说明:Mybatisplus比Mybatis更加的强大.引入jar包时主要一个即可否则会引发冲突.
用户-----MybatisPlus------Mybatis------JDBC
1.5.6Mybatis-plus入门案例
/**
* 测试MybatisPlus新增操作
* 面向对象的方式操作数据库!!!!
*/
public void testInsert() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
int rows = userMapper.insert(user);
System.out.println("入库成功影响:"+rows+"行");
}
1.5.7打印Sql日志文件
编辑YML配置文件,添加mybatis的数据库日志信息.
#打印sql日志
logging:
level:
com.jt.mapper: debug
打印sql如下:
2020-04-07 11:01:55.794 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( name, age, sex ) VALUES ( ?, ?, ? )
2020-04-07 11:01:55.826 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : ==> Parameters: 无名英雄永垂不朽(String), 3(Integer), 男女(String)
2020-04-07 11:01:55.834 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : <== Updates: 1
1.5.8Mybatis与MybatisPlus速度对比
测试策略:
分别利用Mybatis和MybatisPlus方式操作数据库.
1.自己手写sql的方式入库 (快) 执行时间:1107毫秒
2.利用框架动态生成的Sql(反射机制) 执行时间:1328毫秒
INSERT INTO user ( name, age, sex ) VALUES ( ?, ?, ? )
MP速度几乎与真实的Sql速度接近.
//速度对比,1.手写sql 2.动态生成sql
public void testInsert2() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
Long start = System.currentTimeMillis();
//int rows = userMapper.insertUser(user);
int rows = userMapper.insert(user);
Long end = System.currentTimeMillis();
System.out.println("执行时间:"+(end-start)+"毫秒");
//System.out.println("入库成功影响:"+rows+"行");
}
1.6MybatisPlusAPI
//SpringBoot的测试用例,动态的启动了spring容器
public class SpringbootDemoMybatisApplicationTests {
//从容器中动态的注入接口对象
private UserMapper userMapper;
/**
* 测试MybatisfindAll方法是否正确
*/
public void testFindAll() {
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
/**
* 测试MybatisPlus新增操作
* 面向对象的方式操作数据库!!!!
*/
public void testInsert() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
int rows = userMapper.insert(user);
System.out.println("入库成功影响:"+rows+"行");
}
//速度对比,1.手写sql 2.动态生成sql
public void testInsert2() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
Long start = System.currentTimeMillis();
//int rows = userMapper.insertUser(user);
int rows = userMapper.insert(user);
Long end = System.currentTimeMillis();
System.out.println("执行时间:"+(end-start)+"毫秒");
//System.out.println("入库成功影响:"+rows+"行");
}
/**
* 需求1:按照指定的id进行查询 id 1,3,5,9
*sql: select * from user where id=1 and id=3 and id=xxxxx...
*使用in关键字
* select * from user where id in (1,3,5,9);
*实际业务
*用户查询的参数1,3,5,9都是由前台web动态传参,所以在Controler中
*一般采用数组的形式动态接收.
*
*/
("unchecked")
public void test01() {
//一般都是用对象类型进行定义
Integer[] ids = {1,3,5,9};
//数组怎么转化为集合??
List idList = Arrays.asList(ids);
//List idList = org.assertj.core.util.Arrays.asList(ids);
/*List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(3);
idList.add(5);
idList.add(9);*/
List<User> userList = userMapper.selectBatchIds(idList);
System.out.println(userList);
}
/**
* 根据指定的条件查询
* 查询name="王昭君" sex=女的用户 默认使用and方式进行关联
* 需要将查询的字段与值封装到MAP中
* SELECT id,name,age,sex FROM user WHERE sex = ? AND name = ?
*/
public void test02() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("name", "王昭君");//默认使用=号
columnMap.put("sex", "女");
List<User> userList = userMapper.selectByMap(columnMap);
System.out.println(userList);
}
/**
* 查询age>18 and sex=男
*逻辑运算符 > gt, < lt, = eq, >= ge, <= le
*/
public void test03() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18)
.eq("sex", "男");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* name like %精% and sex="女"
* 以精字结尾
* name like %精
* 精%
*/
public void test04() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("name", "精")
.eq("sex", "女");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件:查询年龄在18-35之间的女性用户.
* sql: select * from user where age > 18 and age < 35
*/
public void test05() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.between("age", 18, 35)
.eq("sex", "女");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件:查询年龄大于100岁的,并且按照年龄降序排列,如果年龄相同按照Id降序排列.
*sql中的排序默认根据id升序排列
*SELECT id,name,age,sex FROM user WHERE (age > ?) ORDER BY age DESC,id DESC
*/
public void test06() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",100)
.orderByDesc("age","id");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 子查询: insql
* 条件: 查询age < 100岁的用户,并且性别与name="孙尚香"的性别相同的的用户数据.
*sql: SELECT * FROM USER WHERE age < 100 AND
* sex IN(SELECT sex FROM USER WHERE NAME="孙尚香")
*/
public void test07() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
String name = "'孙尚香'";
queryWrapper.lt("age", 100)
.inSql("sex", "select sex from user where name="+name);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 需求:有时查询可能不需要查询全部字段,会挑选其中几个进行查询.
*1.指定字段进行查询
* 查询age>100岁 只查询Id,name字段
*
*2.只返回查询的字段
*/
public void test08() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id","name").gt("age", 100);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
//只想返回特定的字段
List<Map<String,Object>> mapList = userMapper.selectMaps(queryWrapper);
System.out.println(mapList);
//只返回第一列字段的值 主键值
List<Object> list = userMapper.selectObjs(queryWrapper);
System.out.println(list);
}
/**
* 根据属性中不为null的元素查询数据
* condition:布尔类型的判断 只有当判断为true时,条件生效
*/
public void test09() {
String name = "黑熊精";
String sex = "男";
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//当name属性不为null的时候会动态的拼接name属性值
queryWrapper.eq(!StringUtils.isEmpty(name), "name", name)
.eq(!StringUtils.isEmpty(sex), "sex", sex);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 根据对象中不为null的属性进行查询
*/
public void test10() {
User user = new User();
user.setName("黑熊精")
.setSex("男");
QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
//根据主键查询
public void test11() {
User user = userMapper.selectById(1111);
//根据条件返回一个对象信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", "3");
User user2 = userMapper.selectOne(queryWrapper);
System.out.println(user);
System.out.println(user2);
}
/**
* MP的删除用法
* 案例:
* 1.将name字段值为null的数据进行
* 2.将name字段信息 无名英雄永垂不朽删除
*
*/
public void test12() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
//queryWrapper.isNull("name");
queryWrapper.eq("name", "无名英雄永垂不朽");
userMapper.delete(queryWrapper);
System.out.println("数据库删除成功!!!!");
}
/**
* 数据库更新操作
*
* 1.将大日如来的年龄改为10001 性别 改为男
* entity: 数据修改后的值使用对象封装
* updateWrapper: 修改的条件构造器
*
*
*/
public void test13() {
User user = new User();
user.setAge(10001).setSex("男");
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name","大日如来");
userMapper.update(user, updateWrapper);
}
//2.根据主键1915 将name改为"人民英雄" age=100 性别=男/女
//对象中只有主键充当where条件,其他的字段信息充当set条件
public void test14() {
User user = new User();
user.setId(1915)
.setName("人民英雄")
.setAge(100)
.setSex("男/女");
userMapper.updateById(user);
}
}
2.SpringBoot整合web资源
2.1项目创建
2.1.1知识回顾
1.SpringMVC时创建的项目一定是web项目 打包一定是war包.
2.SpringBoot整合web资源时 .html/.jsp
.html时一般使用 thymeleaf模版引擎进行整合 项目打包.jar包
.jsp方式一般使用web项目的方式进行动态的加载 项目打包.war包
2.2.2创建web项目
1.创建项目
2.在src/main/下添加webapp文件目录
2.2.3导入web页面
在web-INF目录下,创建xxx.jsp文件
2.2.3编辑POM.xml文件
<!--parent当中有一个大型的配置文件,在其中管理了springBoot与第三方整合的 所有(主流的)的jar包的版本 SSM:jar包冲突问题比较严重. -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<!--当前只是引入jar包文件 暂时没有执行. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--spring-boot-starter spring的启动项中自动的完成了项目整合 自动配置 -->
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加属性注入依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--支持热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--引入插件lombok 自动的set/get/构造方法插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--引入数据库驱动 5.5/5.7 5.8数据库则去除版本,使用高版本驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<!--链接数据库代理 使用低版本驱动 -->
<version>5.1.32</version>
</dependency>
<!--springBoot数据库连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--SpringBoot的启动项 开箱即用 -->
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--springBoot默认条件下整合的页面html如果需要整合jsp则需要 手动导入jar包 -->
<!--servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--jstl依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--使jsp页面生效 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
<!--build maven在工作时需要执行的操作. -->
<build>
<!--插件操作 -->
<plugins>
<!--springBoot中负责项目打包/部署/发布等maven操作 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.2.4导入相关配置文件
将mybatis-plus中的配置文件代码全部导入.
2.2.5编辑YML配置文件
说明:编辑配置文件,指定页面跳转路径信息. SpringMVC中有视图解析器的配置.
前缀/后缀
server:
port: 8090 #表示端口号信息
servlet:
context-path: / #项目发布路径
spring:
datasource:
#如果使用高版本驱动则配置如下
#driver-class-name: com.cj.mysql.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#引入mvn配置
mvc:
view:
prefix: /WEB-INF/ # /默认代表根目录 src/main/webapp
suffix: .jsp
#mybatis-plush配置 mp比mybatis功能更加强大 引用一个即可
mybatis-plus:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml #动态的导入xml映射文件
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true #为了user_id与userId完美映射.无需手动转化
#打印sql日志
logging:
level:
com.jt.mapper: debug
2.3实现用户查询
2.3.1编辑UserList.jsp页面
<!--JSP独有的取值方式 jstl标签
${userList}从域中动态取值 -->
<c:forEach items="${userList}" var="u">
<tr>
<th>${u.id}</th>
<th>${u.name}</th>
<th>${u.age}</th>
<th>${u.sex}</th>
</tr>
</c:forEach>
2.3.2编辑UserController
//需要跳转页面
//@RestController //返回的数据都是JSON
public class UserController {
private UserService userService;
/* 交互方式:
* 1.同步 刷新页面同时,需要携带数据 JSP 动态页面独有的方式
* 2.异步 ajax交互方式.
**/
/**
* 需求:
* 1.用户通过http://localhost:8090/findAll请求跳转到userList.jsp页面中
* 2.同时在页面中展现全部的用户数据. 要求使用MP方式查询.
* 取值方法:${userList}
*
*/
("/findAll")
public String findAll(Model model) {
List<User> userList = userService.findAll();
//model一般操作的都是request域
model.addAttribute("userList", userList);
return "userList";//返回页面逻辑名称
}
}
2.3.3编辑UserService
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
//如果需要条件则使用条件构造器编辑,如果不需要条件 则为null接口
public List<User> findAll() {
//面向对象的方式操作数据库!!
return userMapper.selectList(null);
}
}
2.3.4页面效果展现

2.4异步方式实现数据查询
2.4.1jQuery函数类库下载
网址:https://jquery.com/download/
2.4.2引入JS
<%pagelanguage="java"contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<%tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<!--需要导入js函数类库 -->
<scripttype="text/javascript"src="/js/jquery-3.4.1.min.js"></script>
<scripttype="text/javascript">
//校验jQuery是否引入正确.
$(function(){//让页面全部加载完成之后,执行js
//函数式编程 任何的一个动作都是一个function函数
alert("测试jQuery引入是否正常!!!!");
alert("作业1:尽可能多的使用ajax的函数实现业务调用");
alert("作业2:完成用户列表展现");
//1.$.get(url,参数,回调函数....)
//2.$.post(url,参数,回调函数....)
//3.$.getJSON(url,参数,回调函数....)
//4.$.ajax(...)
//提示:1.遍历返回值 2.准备<tr><td></td>....</tr>
})
</script>
<title>ajax的操作方式</title>
</head>
<body>
<tableborder="1px"width="65%"align="center">
<tr>
<tdcolspan="6"align="center"><h3>学生信息</h3></td>
</tr>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
</table>
</body>
</html>
1.1Mybatis介绍
1.1.1Mybatis缺点
1.无论做什么样的操作,所有的sql语句都必须自己手写.
2.Mybatis在进行数据库操作时依然采用"面向过程"的操作方式. 取值操作.
1.2ORM思想
1.2.1ORM介绍
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示着额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。
总结:以面向对象的方式来操作数据库.
1.2.2ORM相关说明
知识回顾: 入库操作
sql: insert into 表名(字段名称....) values (属性的值........) 面向过程的操作.
sql:select * from xxxx where xxx=xxx;
数据库操作升级版
1.update操作(更新操作 增/删/改)
xxxxMapper.insert(user); 参数传递对象即可.代码写到此 结束了.
xxxxMapper.update(user);
2.查询操作
xxxxMapper.select(参数); 需要自动的完成封装
1.3ORM具体实现思路
1.3.1需求说明
用户只需要写xxxMapper.insert(user)操作,则可以自动的实现数据库操作.
提示:
1.需要编辑公共API进行实现
2.深入的解读什么是ORM
3.mysql能否识别java中的user对象?? 只能识别sql语句 如何将对象转化为Sql
实现思路:
1.编辑共同的API 定义单表操作的全部方法!!!! 如果用户需要使用则继承即可.
2.
对象与表完成一一映射. 利用自定义的注解标识对象所映射的表.
对象中的属性与表中的字段一一映射. 可以利用自定义的注解完成映射.
3. 需要编辑底层代码,能够自动的将方法 按照指定的规则完成sql语句的转化.
LG: xxxMapper.insert(user)
SQL: insert into 表名(表中的字段) values (对象中的属性值).
最终将动态生成的Sql交给mybatis或者JDBC去处理.
常识: JDBC操作数据库是最快的.
1.4Mybatis-Plus介绍
1.4.1MP介绍
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
1.4.2特性
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
-
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
-
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
-
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
-
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
-
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
-
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
-
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
-
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
-
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
-
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
1.5Mybatis-plus入门案例
1.5.1导入jar包
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
1.5.2编辑POJO
//生成get/set/toString/equals
(chain=true)//表示链式加载 重写set方法,将对象返回
//添加无参构造 为以后框架的使用做准备
//全部参数的构造方法.
//(value="user")//定义对象与表映射关系 编辑表名
//如果表名与对象的名称一致,则可以省略不写.
public class User {
(type=IdType.AUTO)//标识主键 主键自增.
private Integer id;
//@TableField(value="name")//如果字段的名称与属性名称一致(包含驼峰规则),则可以省略
private String name;//字段与属性一一映射
private Integer age;//user_name userName
private String sex;
}
1.5.3继承公共的接口
//该接口需要交给Spring容器管理
//BaseMapper中的泛型标识操作的具体的表 千万不要写错.
public interface UserMapper extends BaseMapper<User>{
//准备查询全部用户信息的方法
List<User> findAll();
}
1.5.4编辑YML配置文件
server:
port: 8090 #表示端口号信息
servlet:
context-path: / #项目发布路径
spring:
datasource:
#如果使用高版本驱动则配置如下
#driver-class-name: com.cj.mysql.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#mybatis-plush配置 mp比mybatis功能更加强大 引用一个即可
mybatis-plus:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml #动态的导入xml映射文件
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true #为了user_id与userId完美映射.无需手动转化
1.5.5注意事项
说明:Mybatisplus比Mybatis更加的强大.引入jar包时主要一个即可否则会引发冲突.
用户-----MybatisPlus------Mybatis------JDBC
1.5.6Mybatis-plus入门案例
/**
* 测试MybatisPlus新增操作
* 面向对象的方式操作数据库!!!!
*/
public void testInsert() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
int rows = userMapper.insert(user);
System.out.println("入库成功影响:"+rows+"行");
}
1.5.7打印Sql日志文件
编辑YML配置文件,添加mybatis的数据库日志信息.
#打印sql日志
logging:
level:
com.jt.mapper: debug
打印sql如下:
2020-04-07 11:01:55.794 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( name, age, sex ) VALUES ( ?, ?, ? )
2020-04-07 11:01:55.826 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : ==> Parameters: 无名英雄永垂不朽(String), 3(Integer), 男女(String)
2020-04-07 11:01:55.834 DEBUG 3136 --- [ main] com.jt.mapper.UserMapper.insert : <== Updates: 1
1.5.8Mybatis与MybatisPlus速度对比
测试策略:
分别利用Mybatis和MybatisPlus方式操作数据库.
1.自己手写sql的方式入库 (快) 执行时间:1107毫秒
2.利用框架动态生成的Sql(反射机制) 执行时间:1328毫秒
INSERT INTO user ( name, age, sex ) VALUES ( ?, ?, ? )
MP速度几乎与真实的Sql速度接近.
//速度对比,1.手写sql 2.动态生成sql
public void testInsert2() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
Long start = System.currentTimeMillis();
//int rows = userMapper.insertUser(user);
int rows = userMapper.insert(user);
Long end = System.currentTimeMillis();
System.out.println("执行时间:"+(end-start)+"毫秒");
//System.out.println("入库成功影响:"+rows+"行");
}
1.6MybatisPlusAPI
//SpringBoot的测试用例,动态的启动了spring容器
public class SpringbootDemoMybatisApplicationTests {
//从容器中动态的注入接口对象
private UserMapper userMapper;
/**
* 测试MybatisfindAll方法是否正确
*/
public void testFindAll() {
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
/**
* 测试MybatisPlus新增操作
* 面向对象的方式操作数据库!!!!
*/
public void testInsert() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
int rows = userMapper.insert(user);
System.out.println("入库成功影响:"+rows+"行");
}
//速度对比,1.手写sql 2.动态生成sql
public void testInsert2() {
User user = new User();
user.setName("无名英雄永垂不朽");
user.setAge(3);
user.setSex("男女");
Long start = System.currentTimeMillis();
//int rows = userMapper.insertUser(user);
int rows = userMapper.insert(user);
Long end = System.currentTimeMillis();
System.out.println("执行时间:"+(end-start)+"毫秒");
//System.out.println("入库成功影响:"+rows+"行");
}
/**
* 需求1:按照指定的id进行查询 id 1,3,5,9
*sql: select * from user where id=1 and id=3 and id=xxxxx...
*使用in关键字
* select * from user where id in (1,3,5,9);
*实际业务
*用户查询的参数1,3,5,9都是由前台web动态传参,所以在Controler中
*一般采用数组的形式动态接收.
*
*/
("unchecked")
public void test01() {
//一般都是用对象类型进行定义
Integer[] ids = {1,3,5,9};
//数组怎么转化为集合??
List idList = Arrays.asList(ids);
//List idList = org.assertj.core.util.Arrays.asList(ids);
/*List<Integer> idList = new ArrayList<>();
idList.add(1);
idList.add(3);
idList.add(5);
idList.add(9);*/
List<User> userList = userMapper.selectBatchIds(idList);
System.out.println(userList);
}
/**
* 根据指定的条件查询
* 查询name="王昭君" sex=女的用户 默认使用and方式进行关联
* 需要将查询的字段与值封装到MAP中
* SELECT id,name,age,sex FROM user WHERE sex = ? AND name = ?
*/
public void test02() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("name", "王昭君");//默认使用=号
columnMap.put("sex", "女");
List<User> userList = userMapper.selectByMap(columnMap);
System.out.println(userList);
}
/**
* 查询age>18 and sex=男
*逻辑运算符 > gt, < lt, = eq, >= ge, <= le
*/
public void test03() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18)
.eq("sex", "男");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* name like %精% and sex="女"
* 以精字结尾
* name like %精
* 精%
*/
public void test04() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("name", "精")
.eq("sex", "女");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件:查询年龄在18-35之间的女性用户.
* sql: select * from user where age > 18 and age < 35
*/
public void test05() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.between("age", 18, 35)
.eq("sex", "女");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件:查询年龄大于100岁的,并且按照年龄降序排列,如果年龄相同按照Id降序排列.
*sql中的排序默认根据id升序排列
*SELECT id,name,age,sex FROM user WHERE (age > ?) ORDER BY age DESC,id DESC
*/
public void test06() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",100)
.orderByDesc("age","id");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 子查询: insql
* 条件: 查询age < 100岁的用户,并且性别与name="孙尚香"的性别相同的的用户数据.
*sql: SELECT * FROM USER WHERE age < 100 AND
* sex IN(SELECT sex FROM USER WHERE NAME="孙尚香")
*/
public void test07() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
String name = "'孙尚香'";
queryWrapper.lt("age", 100)
.inSql("sex", "select sex from user where name="+name);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 需求:有时查询可能不需要查询全部字段,会挑选其中几个进行查询.
*1.指定字段进行查询
* 查询age>100岁 只查询Id,name字段
*
*2.只返回查询的字段
*/
public void test08() {
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id","name").gt("age", 100);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
//只想返回特定的字段
List<Map<String,Object>> mapList = userMapper.selectMaps(queryWrapper);
System.out.println(mapList);
//只返回第一列字段的值 主键值
List<Object> list = userMapper.selectObjs(queryWrapper);
System.out.println(list);
}
/**
* 根据属性中不为null的元素查询数据
* condition:布尔类型的判断 只有当判断为true时,条件生效
*/
public void test09() {
String name = "黑熊精";
String sex = "男";
//定义条件构造器 负责拼接where条件的
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//当name属性不为null的时候会动态的拼接name属性值
queryWrapper.eq(!StringUtils.isEmpty(name), "name", name)
.eq(!StringUtils.isEmpty(sex), "sex", sex);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 根据对象中不为null的属性进行查询
*/
public void test10() {
User user = new User();
user.setName("黑熊精")
.setSex("男");
QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
//根据主键查询
public void test11() {
User user = userMapper.selectById(1111);
//根据条件返回一个对象信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", "3");
User user2 = userMapper.selectOne(queryWrapper);
System.out.println(user);
System.out.println(user2);
}
/**
* MP的删除用法
* 案例:
* 1.将name字段值为null的数据进行
* 2.将name字段信息 无名英雄永垂不朽删除
*
*/
public void test12() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
//queryWrapper.isNull("name");
queryWrapper.eq("name", "无名英雄永垂不朽");
userMapper.delete(queryWrapper);
System.out.println("数据库删除成功!!!!");
}
/**
* 数据库更新操作
*
* 1.将大日如来的年龄改为10001 性别 改为男
* entity: 数据修改后的值使用对象封装
* updateWrapper: 修改的条件构造器
*
*
*/
public void test13() {
User user = new User();
user.setAge(10001).setSex("男");
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name","大日如来");
userMapper.update(user, updateWrapper);
}
//2.根据主键1915 将name改为"人民英雄" age=100 性别=男/女
//对象中只有主键充当where条件,其他的字段信息充当set条件
public void test14() {
User user = new User();
user.setId(1915)
.setName("人民英雄")
.setAge(100)
.setSex("男/女");
userMapper.updateById(user);
}
}
2.SpringBoot整合web资源
2.1项目创建
2.1.1知识回顾
1.SpringMVC时创建的项目一定是web项目 打包一定是war包.
2.SpringBoot整合web资源时 .html/.jsp
.html时一般使用 thymeleaf模版引擎进行整合 项目打包.jar包
.jsp方式一般使用web项目的方式进行动态的加载 项目打包.war包
2.2.2创建web项目
1.创建项目
2.在src/main/下添加webapp文件目录
2.2.3导入web页面
说明:将课前资料中的web页面导入指定的位置
2.2.3编辑POM.xml文件
<!--parent当中有一个大型的配置文件,在其中管理了springBoot与第三方整合的 所有(主流的)的jar包的版本 SSM:jar包冲突问题比较严重. -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<!--当前只是引入jar包文件 暂时没有执行. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--spring-boot-starter spring的启动项中自动的完成了项目整合 自动配置 -->
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加属性注入依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--支持热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--引入插件lombok 自动的set/get/构造方法插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--引入数据库驱动 5.5/5.7 5.8数据库则去除版本,使用高版本驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<!--链接数据库代理 使用低版本驱动 -->
<version>5.1.32</version>
</dependency>
<!--springBoot数据库连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<!--SpringBoot的启动项 开箱即用 -->
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--springBoot默认条件下整合的页面html如果需要整合jsp则需要 手动导入jar包 -->
<!--servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--jstl依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--使jsp页面生效 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
<!--build maven在工作时需要执行的操作. -->
<build>
<!--插件操作 -->
<plugins>
<!--springBoot中负责项目打包/部署/发布等maven操作 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.2.4导入配置文件
将mybatis-plus中的配置文件代码全部导入.
2.2.5编辑YML配置文件
说明:编辑配置文件,指定页面跳转路径信息. SpringMVC中有视图解析器的配置.
前缀/后缀
server:
port: 8090 #表示端口号信息
servlet:
context-path: / #项目发布路径
spring:
datasource:
#如果使用高版本驱动则配置如下
#driver-class-name: com.cj.mysql.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#引入mvn配置
mvc:
view:
prefix: /WEB-INF/ # /默认代表根目录 src/main/webapp
suffix: .jsp
#mybatis-plush配置 mp比mybatis功能更加强大 引用一个即可
mybatis-plus:
#定义别名包
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml #动态的导入xml映射文件
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true #为了user_id与userId完美映射.无需手动转化
#打印sql日志
logging:
level:
com.jt.mapper: debug
2.3实现用户查询
2.3.1编辑UserList.jsp页面
<!--JSP独有的取值方式 jstl标签
${userList}从域中动态取值 -->
<c:forEach items="${userList}" var="u">
<tr>
<th>${u.id}</th>
<th>${u.name}</th>
<th>${u.age}</th>
<th>${u.sex}</th>
</tr>
</c:forEach>
2.3.2编辑UserController
//需要跳转页面
//@RestController //返回的数据都是JSON
public class UserController {
private UserService userService;
/* 交互方式:
* 1.同步 刷新页面同时,需要携带数据 JSP 动态页面独有的方式
* 2.异步 ajax交互方式.
**/
/**
* 需求:
* 1.用户通过http://localhost:8090/findAll请求跳转到userList.jsp页面中
* 2.同时在页面中展现全部的用户数据. 要求使用MP方式查询.
* 取值方法:${userList}
*
*/
("/findAll")
public String findAll(Model model) {
List<User> userList = userService.findAll();
//model一般操作的都是request域
model.addAttribute("userList", userList);
return "userList";//返回页面逻辑名称
}
}
2.3.3编辑UserService
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
//如果需要条件则使用条件构造器编辑,如果不需要条件 则为null接口
public List<User> findAll() {
//面向对象的方式操作数据库!!
return userMapper.selectList(null);
}
}
2.3.4页面效果展现
2.4异步方式实现数据查询
2.4.1jQuery函数类库下载
网址:https://jquery.com/download/
2.4.2引入JS
<% page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<% taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<!--需要导入js函数类库 -->
<script type="text/javascript" src="/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
//校验jQuery是否引入正确.
$(function(){//让页面全部加载完成之后,执行js
//函数式编程 任何的一个动作都是一个function函数
alert("测试jQuery引入是否正常!!!!");
alert("作业1:尽可能多的使用ajax的函数实现业务调用");
alert("作业2:完成用户列表展现");
//1.$.get(url,参数,回调函数....)
//2.$.post(url,参数,回调函数....)
//3.$.getJSON(url,参数,回调函数....)
//4.$.ajax(...)
//提示:1.遍历返回值 2.准备<tr><td></td>....</tr>
})
</script>
<title>ajax的操作方式</title>
</head>
<body>
<table border="1px" width="65%" align="center">
<tr>
<td colspan="6" align="center"><h3>学生信息</h3></td>
</tr>
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
</tr>
</table>
</body>
</html>

浙公网安备 33010602011771号