二、mybatis-plus与spring boot
2.1 数据库与表
创建一个数据库:
create database mytest;
创建一个表:
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
其对应的数据库 Data 脚本如下:
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2.2 引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.3 配置properties文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
2.4 实体类
@Data
@TableName(value = "user")//指定表名
public class User {
@TableId(value = "id", type = IdType.AUTO) //这个要搭配着表的自增主键使用才可以。
private Long id;
private String name;
private Integer age;
private String email;
}
2.5 mapper
public interface UserMapper extends BaseMapper<User> {
}
2.6 启动类
@SpringBootApplication
//你自己写的UserMapper类的位置
@MapperScan("com.example.mybatisplusdemo.mapper")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
2.7 测试类
@SpringBootTest
class MybatisPlusDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
}
2.8 结果
----- selectAll method test ------
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
2.9 MapperScan和ComponentScan
1、首先@MapperScan和@ComponentScan都是扫描包
2、@ComponentScan是组件扫描注解,用来扫描@Controller @Service @Repository这类,主要就是定义扫描的路径从中找出标志了需要装配的类到Spring容器中
3、@MapperScan 是扫描mapper类的注解,就不用在每个mapper类上加@MapperScan(或者@Mapper)了
这两个注解是可以同时使用的。
2.10 @Mapper 、@MapperScan、 @Repository使用
1、@Mapper
作用:用在接口类上,在编译之后会生成相应的接口实现类,是mybatis的注解。
位置:对应的某个接口类上面
如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用 @MapperScan 。
2、@MapperScan
作用:扫描指定包下所有的接口类,然后所有接口在编译之后都会生成相应的实现类
位置:是在SpringBoot启动类上面添加,
SpringBootApplication 启动类
@MapperScan(“com.springboot.mapper”)
@SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
添加 @MapperScan(“com.springboot.mapper”) 注解以后,扫描 com.springboot.mapper 包下面所有的接口类,在编译之后都会生成相应的实现类。
2.1、@MapperScan 扫描多个包
@MapperScan 也支持多个包的扫描。
@MapperScan({“com.emp.mapper”,“com.dep.mapper”})
@SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
2.2、 @MapperScan 使用表达式,来扫描的包和其子包下面的类
@SpringBootApplication
@MapperScan({“com..mapper","org..mapper”})
public class SpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
3、@Repository
@Repository注解是Spring的注解,把类注册成一个bean。使用了此注解在mapper上后,需要在主启动类添加@MapperScan才能编译之后会生成相应的接口实现类。
@Repository用不用无所谓。如果不用, 使用@Autowire注入mapper接口时, 会出现以下爆红情况. 说什么Could not autowire. No beans of xxxxxxxx。但是其实并不会影响运行, 如果强迫症看到爆红就是不舒服, 可以在每个mapper接口上打上注解 @Repository.
@Repository注解是Spring的注解,使用该注解和@Autowired注解,就不会出现爆红的情况了,原因很简单,因为@Repository注解是Spring的注解,把当前类注册成一个bean了。
4、总结:
@Mapper 是对单个类的注解。是单个操作。
@MapperScan 是对整个包下的所有的接口类的注解。是批量的操作。
@Repository是spring注解需要和@MapperScan配合使用。
三、spring boot注解
3.1 @PathVariable、@RequestParam
使用@RequestParam时,URL是这样的:http://host:port/path?参数名=参数值
使用@PathVariable时,URL是这样的:http://host:port/path/参数值
它们还可以混用。
实例:
@RequestMapping(value = "/email/{name}", method = RequestMethod.GET)
@ResponseBody
public String getEmail(@PathVariable("name") String name, @RequestParam("age") Integer age){
log.info("url:/user/email/{}?age={}", name, age);
return userService.getEmail(name, age);
}
但是注意,它会与下面的方法冲突:
@RequestMapping(value = "/email/{age}", method = RequestMethod.GET)
@ResponseBody
public String getEmail1(@PathVariable("age") Integer age, @RequestParam("name") String name){
log.info("url:/user/email/{}?name={}", age, name);
return userService.getEmail(name, age);
}
对于请求:http://localhost:8080/user/email/21?name=Jack,servlet不知道该分发给谁来处理。
ERROR: Ambiguous handler methods mapped for '/user/email/21': {public java.lang.String com.example.mybatisplusdemo.controller.UserController.getEmail1(java.lang.Integer,java.lang.String), public java.lang.String com.example.mybatisplusdemo.controller.UserController.getEmail(java.lang.String,java.lang.Integer)}]
在注释掉getEmail1
方法后,请求的url如下,结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7FCd9TS1-1637809906588)(D:\fangtuoqian1\Documents\工作学习记录\image-20211124181804203.png)]
3.2 @SpringBootTest
该注解用于测试类上。如果不加这个注解,测试类无法自动注入bean。
二、mybatis-plus增删改查
2.1 查
@Test
public void test1() {
userManagerImpl.list().forEach(System.out::println);
}
@Test
public void test2() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age", 23);
userManagerImpl.list(wrapper).forEach(System.out::println);
}
@Test
public void test3() {
List<Map<String, Object>> maps = userManagerImpl.listMaps();
for (Map<String, Object> map: maps
) {
for (Map.Entry<String, Object> entry: map.entrySet()
) {
System.out.printf("%s=%s, ", entry.getKey(), entry.getValue());
}
System.out.println();
}
}
@Test
public void test4() {
Map<String, Object> map = new HashMap<>(16);
map.put("age", 21);
map.put("name", "Sandy");
List<User> users = userManagerImpl.listByMap(map);
users.forEach(System.out::println);
}
@Test
public void test5() {
//返回的是id,为Long型
userManagerImpl.listObjs().forEach(System.out::println);
}
2.2 增
@Test
public void test6() {
User user = new User();
user.setName("ZhouSb");
user.setAge(29);
user.setEmail("zhoupeigen@qq.com");
boolean save = userManagerImpl.save(user);
System.out.println(save);
}
@Test
public void test7() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.setName("test_" + (i+1));
user.setAge(i+20);
user.setEmail("test" + (i+1) + "@qq.com");
users.add(user);
}
boolean saveBatch = userManagerImpl.saveBatch(users);
log.info("{}", saveBatch);
}
@Test
public void test7_() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
//从这里可以看出,即使是自增主键,如果指定了id值,那么最终的id是以指定的为准
//如果没有指定,则自增
user.setId((long) (i+6));
user.setName("test_" + (i+1));
user.setAge(i+20);
user.setEmail("test" + (i+1) + "@qq.com");
users.add(user);
}
boolean saveBatch = userManagerImpl.saveBatch(users);
log.info("{}", saveBatch);
userManagerImpl.list().forEach(System.out::println);
}
2.3 改
@Test
public void test8() {
//sql : update user set email="test1@163.com" where name="test_1";
//使用条件构造器实现
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("name", "test_1");
User user = new User();
user.setEmail("test1@163.com");
boolean update = userManagerImpl.update(user, wrapper);
log.info("{}", update);
userManagerImpl.list().forEach(System.out::println);
}
@Test
public void test9() {
//sql : update user set email="test2@gmail.com" where name="test_2";
//使用条件构造器实现
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
//用于添加where条件
wrapper.eq("name", "test_2");
//注意这个只用于设置sql语句的set部分
wrapper.setSql("email='test2@gmail.com'");
userManagerImpl.update(wrapper);
userManagerImpl.list().forEach(System.out::println);
}
2.4 删
@Test
public void test10() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "ZhouSb");
System.out.println(userManagerImpl.remove(wrapper));
userManagerImpl.list().forEach(System.out::println);
}
@Test
public void test11() {
User user = new User();
user.setId(8L);
user.setName("");
user.setAge(0);
user.setEmail("");
//可以看到这个方法只关注id,其余属性存不存在,是多少都无关
System.out.println(userManagerImpl.removeById(user));
//id为8的数据已被删除,尽管它的name,age,email都与上面的对象不相同
userManagerImpl.list().forEach(System.out::println);
}