一,相关注解
1.1@TableName
TableName注解是用于解决实际开发中数据库中的表名和实体类名字不一致情况的。
当数据库表名(t_user)与实体类(User)不一致时就可以在实体类前加上@TableName("t_user"),让实体类识别对应的表,即可成功执行SQL语句。
@Data
@Setter
@Getter
@TableName("t_user")//解决数据库与实体类字段不一致
public class User {
private Long id;
private String name;
private Integer age;
private Integer gender;
}
1.2@TableId
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认基于雪花算法的策略生成id。但是如果实体类和表中表示主键的字段名不是id,而是其他字段,例如uid,MyBatis-Plus无法自动识别uid为主键的。可以通过@TableId 指定主键字段为除了id之外的某个值
@Data
@Setter
@Getter
@TableName("t_user")//解决数据库与实体类字段不一致
public class User {
@TableId(type = IdType.AUTO)//申明实体类主键
private Long id;
private String name;
private Integer age;
private Integer gender;
}
@TableId的type属性
type属性用来定义主键策略,常用的type属性值如下:
IdType.ASSIGN_ID(默认) :基于雪花算法的策略生成数据id,与数据库id是否设置自增无关
IdType.AUTO :使用数据库的自增策略,注意,该类型请确保数据库设置了id自增,否则无效
1.3@TableField
TableField注解是用于解决实际开发中数据库表中的字段名和实体类字段名不一致情况的。
1、如果实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名,例如:实体类属性userName,表中字段user_name此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格,相当于在MyBatis中配置。
2、若实体类中的属性和表中的字段名不一致,例如实体类属性name,表中字段username,这时候就需要在实体类属性上使用@TableField("username")设置属性所对应的字段名
@Data
@Setter
@Getter
@TableName("t_user")//解决数据库与实体类字段不一致
public class User {
@TableId(type = IdType.AUTO)//申明实体类主键
private Long id;
@TableField(value = "username")
private String name;
private Integer age;
private Integer gender;
}
1.4@TableLogic
@TableLogic主要是实现逻辑删除的。
逻辑删除和物理删除分别指的是什么?
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
逻辑删除的使用场景:可以进行数据恢复
@Data
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_users")//解决数据库与实体类字段不一致
public class Users {
@TableId(type = IdType.AUTO)//申明实体类主键
private Long id;
private String name;
private Integer age;
private Integer gender;
@TableLogic
private Integer isDelete;
}
二、代码生成器
在项目开发过程中,关注点更多是在业务功能的开发及保证业务流程的正确性上,对于重复性的代码编写占据了程 序员大量的时间和精力,而这些代码往往都是具有规律的。就如controller、service、serviceImpl、dao、daoImpl、model、jsp的结构,用户、角色、权限等等模块都有类似的结构。针对这部分代码,就可以使用代码生 成器,让计算机自动帮我们生成代码,将我们的双手解脱出来,减小了手工的重复劳动。
package com.gcxy.utils;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.ArrayList;
import java.util.List;
public class CodeGenerator {
public static void main(String[] args) {
String url = "jdbc:mysql:///gcxy_teach?serverTimezone=Asia/Shanghai&characterEncoding=utf-8";
String username = "root";
String password = "123456";
String model = "";//表示项目的模块名称
String outPath = System.getProperty("user.dir") + "/" + model + "/src/main/java";//文件输出路径
String parent = "com.gcxy";//父包的名称
String modelName = "";//模块名称
String entity = "entity";//实体类
String mapper="mapper";//接口
String service="service";
String serviceImpl="service.Impl";
String controller ="controller";
String mapperXml ="mapper.xml";
List<String> tables = new ArrayList<>();
tables.add("phone");//添加表
tables.add("dep");
tables.add("stu");
FastAutoGenerator.create(url, username, password)
//全局配置
.globalConfig(builder -> {
builder.author("huangR") // 设置作者
// .enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件,《可覆盖同名文件》
.outputDir(outPath)// 指定输出目录
.disableOpenDir();//生成后不打开目录
})
// .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
// int typeCode = metaInfo.getJdbcType().TYPE_CODE;
// if (typeCode == Types.SMALLINT) {
// // 自定义类型转换
// return DbColumnType.INTEGER;
// }
// return typeRegistry.getColumnType(metaInfo);
//
// }))
//包配置
.packageConfig(builder -> {
builder.parent(parent) // 设置父包名
.moduleName(modelName) // 设置父包模块名
.entity(entity)//设置实体类文件名
.mapper(mapper)
.service(service)
.serviceImpl(serviceImpl)
.controller(controller)
.xml(mapperXml);
// .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
})
//模板配置
//策略配置
.strategyConfig(builder -> {
builder.addInclude(tables) // 设置需要生成的表名
.entityBuilder()//开启生成实体类
.enableLombok()//开启lombok模型
.mapperBuilder()//开启生成mapper
.superClass(BaseMapper.class)
// .enableMapperAnnotation()//开启mapper注解
.formatMapperFileName("%sMapper")//格式化mapper名称
.formatXmlFileName("%sMapper")//格式化xml名称
.serviceBuilder()//开启生成service
.formatServiceFileName("%sService")//格式化service接口文件名称
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()//开启生成controller
.formatFileName("%sController")
.enableRestStyle();
// .addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.templateEngine(new VelocityTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
三,增删改查
3.1新增
使用mapper层查询数据在mapper中之封装了insert()方法
public void contextLoads() {
User user = new User();
user.setAge(19);
user.setGender(1);
user.setName("小黄");
userMapper.insert(user);
Long id=user.getId();
System.out.println("id:"+id);
}
在service中封装的插入方法
public void contextLoads() {
User user = new User();
user.setAge(19);
user.setGender(1);
user.setName("小黄");
boolean isSuccess=userService.save(user);
Long id = user.getId();
System.out.println("返回结果:"+isSuccess+"id:"+id);
}
伪批量插入
public void contextLoads() {
List<User> userList=new ArrayList<>();
for (int i=1;i<5;i++){
User user=new User();
user.setAge(19+i);
user.setGender(1+i);
user.setName("小黄"+i);
userList.add(user);
}
boolean isSuccess=userService.saveBatch(userList);
System.out.println("返回结果:"+isSuccess);
}
批量保存或更新
@Test
pubic void contextLoads() {
List<User> userList=new ArrayList<>();
for (int i=8;i<30;i++){
User user=new User();
user.setAge(19+i);
user.setGender(1+i);
user.setName("小黄"+i);
userList.add(user);
}
boolean isSuccess=userService.saveOrUpdateBatch(userList);
System.out.println("返回结果:"+isSuccess);
}
3.2删除
mapper层删除,根据主键id删除数据(直接传id)
@Test
pubic void contextLoads() {
int count= userMapper.deleteById(9L);
System.out.println("删除了"+count+"条数据");
}
根据主键id删除(传实体类)
@Test
pubic void contextLoads() {
User user = new User();
user.setId(8L);
int count = userMapper.deleteById(user);
System.out.println("删除了"+count+"条数据");
}
根据主键id批量删除
@Test
pubic void contextLoads() {
List<Long> ids=new ArrayList<>();
ids.add(1L);
ids.add(2L);
// delete from t_user where id in (1,2)
userMapper.deleteBatchIds(ids);
}
通过构造Wrapper构造器删除
@Test
pubic void contextLoads() {
QueryWrapper wrapper=new QueryWrapper<>();
wrapper.eq("name","小黄3");
wrapper.eq("age","22");
// delete from t_user where (name="小黄" and age=22)
userMapper.delete(wrapper);
}
lambda表达式
@Test
pubic void contextLoads() {
QueryWrapper wrapper=new QueryWrapper<>();
wrapper.eq("name","小黄3");
wrapper.eq("age","22");
// delete from t_user where (name="小黄" and age=22)
userMapper.delete(new QueryWrapper<User>()
.lambda()
.eq(User::getName,"小黄9")
.eq(User::getAge,28)
);
}
使用map设置条件删除
@Test
pubic void contextLoads() {
Map<String ,Object> col=new HashMap<>();
col.put("name","小黄8");
col.put("age",27);
int count =userMapper.deleteByMap(col);
System.out.println("删除"+count+"条");
}
3.3修改
更新数据mapper层
@Test
pubic void contextLoads() {
User user=User.builder()
.name("小强")
.id(5L)
.gender(0)
.build();
int count = userMapper.updateById(user);
System.out.println("更新了"+count+"条数据");
}
通过Wrapper进行更新
@Test
pubic void contextLoads() {
User user = User.builder().name("小红红").gender(1).build();
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("age",22);
int count = userMapper.update(user,userUpdateWrapper);
System.out.println("更新了"+count+"条数据");
}
service层,更新
@Test
pubic void contextLoads() {
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.set("age", 30);
userUpdateWrapper.eq("name", "小黄19");
userService.update(userUpdateWrapper);
}
3.4查询
查询数据mapper层(根据id查询)
@Test
public void contextLoads() {
User user=userMapper.selectById(5L);
System.out.println(user.toString());
}
通过构造Wrapper进行查询
@Test
public void contextLoads() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//设置查询字段,仅查询name,id
queryWrapper.select("id","name");
//添加查询条件
queryWrapper.eq("id",6L);
User user =userMapper.selectOne(queryWrapper);
System.out.println(user.toString());
}
根据id批量查询
@Test
public void contextLoads() {
List<User> userList = userMapper.selectBatchIds(Arrays.asList(5L,6L,7L));
通过条件构造Wrapper组装查询条件,查询全部数据
@Test
public void contextLoads() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
//设置查询字段,仅查询name,id
queryWrapper.select("id","name");
//添加条件
queryWrapper.eq("age",12);
List<User> users=userMapper.selectList(queryWrapper);//查询全部数据
}
根据columnMap设置查询条件
@Test
public void contextLoads() {
Map<String,Object> colMap=new HashMap<>();
colMap.put("name","ooo");
colMap.put("age",12);
List<User> userList=userMapper.selectByMap(colMap);//使用Map构造
}
根据wrapper条件,查询记录总数
@Test
public void contextLoads() {
QueryWrapper<User> queryWrapper1=new QueryWrapper<>();
queryWrapper1.eq("name","ooo").eq("age",12);
long count =userMapper.selectCount(queryWrapper1);
}
service层根据id去获取数据
@Test
public void contextLoads() {
User user =userService.getById(6L);//根据id去获取数据
}
通过wrapper 条件查询一条数据,当结果出现多条数据时会抛出异常
@Test
public void contextLoads() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name","ooo").eq("id",5L);
User user =userService.getOne(queryWrapper);
}
通过List开头的方法来查询多条数据
@Test
public void contextLoads() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name","ooo").eq("id",5L);
List<User> users=userService.list(queryWrapper);
}
根据id列表查询数据
@Test
public void contextLoads() {
List<User> userList= userService.listByIds(Arrays.asList(5L,6L));
}