Mybaits缺点:
1.Mybatis操作数据库的过程中,需要编辑大量的sql语句.无论该sql是否复杂或者简单.
2.Mybatis操作时在xml配置文件中需要额外记忆单独的标签.
需求:能否实现单表操作的CRUD的全自动的实现.能否实现真正的ORM映射?
要求: 利用面向对象的方式操作数据库.
特点:
1.操作数据库的面向对象.
userMapper.insert(user对象); ------->自己编辑sql语句
2.查询数据库的面向对象.
userMapper.selectByWhere(user对象); ------>动态的生成Sql------>自动实现结果集封装.
要求:实现单表的自动的CRUD操作.
例子:
User user = new Uesr();
user.setId(xx).setName(xx).setAge(xx).setSex(xx);
userMapper.insertUser(user);
框架内部实现过程:
核心:数据库只能识别sql语句.框架需要将对象转化为sql.
核心配置:
1.User对象与数据库的表 一一映射!
解决方法: 自定义注解标识表与对象的关系
2.User对象的属性与数据表中的字段一一映射!
解决方法:自定义注解完成属性与字段的映射
3.将CURD的方法进行统一的定义.形成工具API接口
解决方法:利用公共的mapper接口 BaseMapper,在其中定义几乎所有的单表的CURD操作.
4.将接口方法按照数据库方式转化为特定的sql语句.
1.用户的调用 userMapper.insert(user)
2.拼接特定的sql:
insert into 表名(字段名......) values(属性值......);
一般利用反射技术,可以通过对象或者有关对象的全部信息(注解,属性,属性值)
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
使用的数据库是mysql
数据库sql文件 jtdb .sql 在下方的百度网盘地址 点击下载即可
百度网盘 链接: https://pan.baidu.com/s/1OOKgsltlItJ-lIy-F9EFuw 提取码: cpih
导入方式:
1.通过cmd的方式打开mysql数据库
2.找到sql文件的储存位置
3.通过命令source + sql文件位置的方式 即可导入完成
使用STS创建一个spring项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>Mybatis-pulsdome</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Mybatis-pulsdome</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<!--添加maven插件 -->
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<!--SpringBoot测试方法 -->
<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>
<!--引入数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>runtime</scope>
</dependency>
<!--springBoot数据库连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--spring整合mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意包路径
@Data
@Accessors(chain=true) //链式加载
@TableName //标识对象与表之间的关联关系
public class User {
//简化步骤:如果属性的名称与映射的名称一致,则可以省略不写
@TableId(type=IdType.AUTO) //定义主键 主键自增
private Integer id;
//对象的属性与表中的字段.
//@TableField(value="name")
private String name;
private Integer age;
private String sex;
}
注解:
1.@Date @Accessors(chain=true) 是来着lombox插件的方法 是帮助我们生成Get,Set方法 没有安装lombox的 需要手写get set方法
2.@TableName 是mybatisPuls的注解 是标识对象与表之间的关联关系 如果数据库的表名 和 我们家的类名并不相同 可在注解后指定关联数据库的表名 如:@TableName(“db_user”)
3.@TableId(type=IdType.AUTO) 是指定主键 而后面的type=IdType.AUTO 属性 表示 数据库中表的id属性是自增的
package cn.tedu.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.tedu.pojo.User;
@Mapper
public interface UserMapper extends BaseMapper<User>{
}
值得注意的是:
使用myBatisPuls 其mapper接口 必须继承 BaseMapper 并且在泛型内指定 此接口映射的pojo类
找到spring配置文件 按F2将文件后缀更改为 application.yml
spring:
datasource:
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: 123456 #写自己家mysql数据库的账号密码
#mybatis-plush配置
mybatis-plus:
#配置文件的资源加载路径
#mapper-locations: classpath:/mybatis/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
创建测试方法
书写TestUserMapper测试方法
package cn.tedu.mapper;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import cn.tedu.pojo.User;
@SpringBootTest //添加测试注解
public class TestUserMapper {
@Autowired //注入mapper对象
private UserMapper userMapper;
/**
* 1.入门案例
* 要求:查询全部的用户信息 不需要写where条件
* 注意事项:利用MP的方法和自己的接口方法 名称不能重复.
*
* 参数说明:queryWrapper 动态生成sql语句中的where条件
*/
@Test
public void test01() {
List<User> userList = userMapper.selectList(null);
System.out.println(userList);
}
}
解析:
利用MP调用其中的方法,可以动态生成sql语句查询数据库
这里选用的是
userMapper.selectList(null);
其方法内传入的参数 queryWrapper 是条件构造器 目的是生成sql语句 where 之后的条件
如 :select * from user where id =1;
而这里我们传入的是null值 表示查询所有
其sql语句是 select * from user
/**
* 练习1: 查询id信息为1,3,4,5,6用户数据
* sql: select * from user where id in (1,2,3,4,5,6);
* 思考:id可以利用数组进行接收 利用数组查询数据
*/
@Test
public void test02() {
List<Integer> idList = new ArrayList<Integer>();
idList.add(1);
idList.add(3);
idList.add(4);
idList.add(5);
idList.add(6);
//以对象的方式进行数据库操作
List<User> userList = userMapper.selectBatchIds(idList);
System.out.println(userList);
}
说明:根据字段查询用户信息
/**
* 练习2: 根据name="黑熊精" age="3000"查询数据信息
* SelectByMap:根据具体的字段查询用户信息.
* sql语句: select * from user where name="黑熊精" and age=3000
* 规则:默认使用and连接符.
*/
@Test
public void test03() {
Map<String,Object> map = new HashMap<>();
//key="字段名称" value="字段值"
map.put("name", "黑熊精");
map.put("age", 3000);
List<User> userList = userMapper.selectByMap(map);
System.out.println(userList);
}
/**
* 4.name属性中包含"精"的数据,并且为女性
* sql: SELECT * FROM USER WHERE NAME LIKE "%精%" AND sex = "女"
* queryWrapper: 条件构造器
* 作用 动态拼接sql的where条件
* 逻辑运算符: >gt , =ge, <= le
*/
@Test
public void test04() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "精")
.eq("sex", "女");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 查询年龄在18-35之间的女性用户.
* sql: SELECT * FROM USER WHERE age BETWEEN 18 AND 35 AND sex ="女";
*/
@Test
public void test05() {
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:SELECT * FROM USER WHERE age > 100 ORDER BY age DESC,id DESC;
*/
@Test
public void test06() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 100)
.orderByDesc("age","id");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件: 查询名称以"乔"结尾的,并且性别为女,并且age小于30岁.按照年龄降序排列.
* SQL:
* SELECT * FROM USER WHERE (NAME LIKE "%乔" AND sex="女"
AND age < 30) ORDER BY age DESC;
*/
@Test
public void test07() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("name", "乔")
.eq("sex", "女")
.lt("age", 30)
.orderByDesc("age");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
说明:适用于子查询
/**
* 查询age < 100岁的用户,并且性别与name="孙尚香"的性别相同的的用户数据.
* 分析: age<100 sex=男/女
* sql:SELECT * FROM USER WHERE age < 100 AND
sex in(
SELECT sex FROM USER WHERE NAME = "孙尚香"
)
*/
@Test
public void test08() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age", 100)
.inSql("sex", "select sex from user where name ='孙尚香'");
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 需求: 有时可能不需要查询全部的数据库的表字段
* 查询age为18岁的用户的名称和id.
* select:挑选字段的属性.
* 查询结果:User(id=12, name=貂蝉, age=null, sex=null)
*/
@Test
public void test09() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name","id")
.eq("age", 18);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 条件判断
* 以name和sex不为null的数据当做where条件.
* condition作用:
* 判断参数是否拼接为where条件
* 结果true, 动态拼接参数
* 结果false, 参数不会动态拼接
* 应用场景:
* 接收前台的参数时,参数可能为null或者其他的数值类型时
* 需要添加判断.
* 业务需求:
* 如果age>18时,才能查询年龄
*/
@Test
public void test10() {
String name = null;
int age = 18;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//name属性的值,不为null时,才会拼接where条件
queryWrapper.eq(!StringUtils.isEmpty(name), "name", name);
queryWrapper.eq(age>18, "age", age);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
/**
* 根据对象查询数据库
* 条件:根据对象中不为null的属性充当where条件
* 需求:查询age=18的用户信息 性别=女
* 说明:利用对象的方式查询时,逻辑运算符都是"="号
*/
@Test
public void test11() {
User user = new User();
user.setAge(18)
.setSex("女");
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
List<User> userList = userMapper.selectList(queryWrapper);
System.out.println(userList);
}
说明:只查询主键信息(第一列)数据
/**
* 需求:只查询主键的信息.
* 类比: select
* sql: SELECT id FROM USER where age >18
*/
@Test
public void test12() {
QueryWrapper<User> queryWrapper2 = new QueryWrapper<User>();
queryWrapper2.select("id");
//查询的List对象信息
userMapper.selectList(queryWrapper2);
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.gt("age", 18);
//只查询主键信息
List<Object> idList = userMapper.selectObjs(queryWrapper);
System.out.println(idList);
}
/**
* 获取任意的字段信息
* 需求:查询用户信息 只想获取id和name的值.不想获取age/sex
* sql: select id,name from user where age > 18;
*/
@Test
public void test13() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.select("id","name")
.gt("age", 18);
//获取全部的对象信息
List<User> userList = userMapper.selectList(queryWrapper);
//获取字段的信息
List<Map<String,Object>> listMap = userMapper.selectMaps(queryWrapper);
System.out.println(userList);
System.out.println(listMap);
}
@Test
public void test14() {
User user = new User();
user.setName("外国人永久居住权")
.setSex("男")
.setAge(30);
userMapper.insert(user);
}
/**
* 删除用户信息
*/
@Test
public void test15() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.eq("name", "外国人永久居住权");
//根据多个条件 删除用户数据.
userMapper.delete(queryWrapper);
//根据集合中的数据.批量删除用户信息
Integer[] ids = {
2000,2001};
List<Integer> idList = Arrays.asList(ids);
userMapper.deleteBatchIds(idList);
//id 代表主键信息 根据主键进行删除.
userMapper.deleteById(2000);
//挑选字段和属性进行删除.
Map<String,Object> columnMap = new HashMap<String, Object>();
columnMap.put("name", "疫情");
userMapper.deleteByMap(columnMap);
}
/**
* 更新操作
* updateById: 根据主键信息修改数据.
* 主键信息必须添加充当where条件,
* 根据对象中不为null的数据,充当set条件.
* sql: update user set name="xx",age=xxx,sex=xx where id=23
*
* update方法说明:
* 参数1:entity 修改后的数据结果
* 参数2:updateWrapper 修改的条件构造器
* 案例:
* 将杨颖改为范冰冰 修改年龄/性别
* sql : update user set name="xxxx",age=xxx,sex=xxx
* where name = "杨颖";
*
*/
@Test
public void test16() {
User user = new User();
user.setId(23).setName("潘凤").setAge(35).setSex("男");
userMapper.updateById(user);
User user2 = new User();
user2.setName("范冰冰").setAge(40).setSex("女");
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "杨颖");
userMapper.update(user2, updateWrapper);
}