Mybatis-Plus
一、代码生成器
Mybatis-Plus代码生成器是一个用于快速生成Mybatis Plus项目的代码的工具。它可以帮助你自动生成实体类、Mapper接口、Service接口和实现类等,从而减少手动编写代码的工作量。
具体代码如下:
String url="jdbc:mysql://localhost:3306/gcxy_teach?serverTimezone=Asia/Shanghai&characterEncoding=utf-8";
String username="root";
String password="201806";
String module="";//表示项目的模块名称
String outPath=System.getProperty("user.dir")+"/"+module+"/src/main/java";//文件输出路径
String parent="com.cqgcxy";//父包的名称
String moduleName="";//模块名
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("account");
tables.add("phone");
tables.add("dep");
tables.add("stu");
FastAutoGenerator.create(url, username, password)
//全局配置
.globalConfig(builder -> {
builder.author("huliguo") // 设置作者
// .enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(outPath) // 指定输出目录
.disableOpenDir();//生成后不打开目录
})
//包配置
.packageConfig(builder -> {
builder.parent(parent) // 设置父包名
.moduleName(moduleName) // 设置父包模块名
.entity(entity)//设置实体类包名称
.mapper(mapper)
.service(service)
.serviceImpl(serviceImpl)
.controller(controller)
.xml(mapperXml);//mapper.xml
})
//策略配置
.strategyConfig(builder -> {
builder.addInclude(tables) // 设置需要生成的表名
// .addTablePrefix("t_", "c_"); // 设置过滤表前缀
.entityBuilder()//开启生成实体类
.enableLombok()//开启lombok生成getter、setter
.mapperBuilder()//开启mapper生成
.superClass(BaseMapper.class)
// .enableMapperAnnotation()//开启mapper注解
.formatMapperFileName("%sMapper")//格式化mapper名称
.formatXmlFileName("%sMapper")//格式化xml名称
.serviceBuilder()//开启生成service
.formatServiceFileName("%sService")//格式化service接口文件名称
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()//开启生成controller
.formatFileName("%sController")//格式化controller名称
.enableRestStyle();
})
.templateEngine(new VelocityTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
运行该类即可生成。
二、实体类的常用注解
@Data
@Data
是Lombok库中的一个注解,用于自动生成Java类的getter、setter方法、equals、hashCode和toString方法 。用法:
@Data
public class OrderVo {
//字段
}
@Builder
@Builder
也是Lombok库中的一个注解,用于简化构建器模式的代码编写。通过使用@Builder
注解,可以自动生成一个包含所有字段的静态内部类,并提供了链式调用的方法来设置字段值。这样可以方便地创建对象,而不需要手动编写构造函数和setter方法。 用法:1.在实体类写上@Builder注解
@Builder
public class User{
private Integer id;
private String name;
private Integer age;
private String sex;
}
2.创建该对象时就能且只能以这样的方式生成:
User user =User.builder().name("xwa").age(11).sex("男").build();
@TableName
@TableName
是MyBatis-Plus中的一个注解,用于指定实体类对应的数据库表名。通过在实体类上添加该注解并设置属性值,可以自定义表名。 用法:
@TableName("t_user")//自动映射数据库中t_user表
public class User {
private int id;//主键自增id:如果不写这个字段,数据库映射的时候,会找不到这个字段,自动添加none类型none值,再去数据库找,就会报错
//其余数据库字段
}
@TableId
@TableId
是MyBatis-Plus中的一个注解,用于指定实体类中作为主键的字段。通过在实体类中的某个字段上添加该注解并设置属性值,可以指定该字段为主键
@TableName("t_user")//自动映射数据库中t_user表
public class User {
@TableId(type = IdType.AUTO)//IdType.AUTO类型表示自动增长
private int id;
private Integer age;
private String name;
}
@Getter和@Setter
User
实体类使用了@Getter和@Setter注解,注解会自动为所有字段生成getter和setter方法。 用法和@Data注解一样。
三、 QueryWrapper 类
QueryWrapper
是MyBatis-Plus提供的一个查询条件封装类,它主要用于构建数据库查询条件。QueryWrapper
提供了一种更简洁、易用的方式来构建查询条件,使得查询操作更加灵活。同时,QueryWrapper也是用于生成sql的where条件和entity属性的重要工具。
QueryWrapper的常用方法主要包括以下几种:
-
and()和or():分别用于拼接+?AND 字段=值 和 +?OR 字段=值的条件语句。
-
eq():用于生成等于(=)条件,例如:eq(“name”, “张三”)。
-
ne():用于生成不等于(!=)条件,例如:ne(“age”, 18)。
-
gt():用于生成大于(>)条件,例如:gt(“age”, 20)。
-
ge():用于生成大于等于(>=)条件,例如:ge(“age”, 20)。
-
lt():用于生成小于(<)条件,例如:lt(“age”, 30)。
-
le():用于生成小于等于(<=)条件,例如:le(“age”, 30)。
-
between():用于生成在…之间(BETWEEN…AND…)的条件,例如:between(“age”, 20, 30)。
-
like():用于生成模糊查询like条件,例如:like(“name”, “张”)。也可leftLike(“name”, “张”)/rightLike(“name”, “张”)
-
in():用于生成in查询条件,例如:in(“id”, Arrays.asList(1, 2, 3))。
-
notIn():用于生成not in查询条件,例如:notIn(“id”, Arrays.asList(1, 2, 3))。
-
isNull()和isNotNull():用于生成是否为null的条件,例如:isNull(“address”)和isNotNull(“address”)。
-
eqLike()和neqLike():用于生成等于或不等于某个值并且符合like条件的查询,例如:eqLike(“name”, “张”)和neqLike(“name”, “李”)。
-
groupBy():用于对结果进行分组,例如:groupBy(“department”)。
-
select():用于指定要查询的字段,例如:select(“name”, “age”)。
-
lastSql():获取构建的SQL语句。
用法:
QueryWrapper<User> queryWrapper= new QueryWrapper<>(); queryWrapper.select("id","name").eq("id",5);//后面可以自己根据条件.出对应的方法 User user1=userMapper.selectOne(queryWrapper);
四、BaseMapper接口
测试类准备(这里把后面的Service接口也一起注入了):
@SpringBootTest
class MybatisPublsApplicationTests {
@Autowired//注入
UserMapper userMapper;
@Autowired
UserService userService;
@Autowired
UsersMapper usersMapper;
@Test
void contextLoads() {}
}
BaseMapper
接口是MyBatis-Plus框架提供的一个基础的Mapper接口,用于简化数据库操作。它包含了一些常用的方法,如插入、删除、更新和查询等。
通常情况下,我们只需要继承BaseMapper
接口并指定对应的实体类作为泛型参数,就可以使用该接口提供的方法进行数据库操作了。 用法:
public interface UserMapper extends BaseMapper<User> {
// 可以在这里定义自定义的数据库操作方法
}
在上面的例子中,UserMapper
接口继承了BaseMapper
,表示该接口将操作与User
实体类相关的数据库表。如果需要定义自定义的数据库操作方法,可以在该接口中添加相应的方法即可。
1.insert():
//插入操作
User user=new User();
user.setAge(10);
userMapper.insert(user);
2.deleteById(int id):
//根据主键id删除数据 (直接传id)
int count=userMapper.deleteById(1);
System.out.println("删除了"+count+"条数据");
3.deleteById(User user):
//根据主键id删除(传实体类)
User user=new User();
user.setId(8);
int count=userMapper.deleteById(user);
System.out.println("删除了"+count+"条数据");
4.deleteBatchIds():
//根据主键id批量删除数据
// delete from user where id in (1,2);
List<Integer> ids =new ArrayList<>();
ids.add(1);
ids.add(2);
int count=userMapper.deleteBatchIds(ids);
System.out.println("删除了"+count+"条数据");
5.delete():
//通过构造Wrapper构造器删除
QueryWrapper wrapper=new QueryWrapper<>();
wrapper.eq("age",10);
wrapper.eq("name","小王");
userMapper.delete(wrapper);
//lambda表达式
userMapper.delete(new QueryWrapper<>().lambda()
.eq(User::getName,"小王")
.eq(User::getAge,10)
);
6.deleteByMap():
//使用map设置条件删除
Map<String,Object> col=new HashMap<>();
col.put("name","小王");
col.put("age",11);
int count=userMapper.deleteByMap(col);
System.out.println("删除了"+count+"条数据");
7.updateById():
//根据id更新数据
User user =User.builder().name("小明").id(2).age(11).build();//链式编程 lombok中实体@Builder
int count = userMapper.updateById(user);
System.out.println("更新了"+count+"条数据");
8.update():
//通过wrapper进行更新
User user =User.builder().name("小小明").build();//实体类
UpdateWrapper<User> userUpdateWrapper=new UpdateWrapper<>();
userUpdateWrapper.eq("age",13);//条件
userMapper.update(user,userUpdateWrapper);
9.selectById():
//根据id查询数据
User user =userMapper.selectById(7);
System.out.println(user.toString());
10.selectOne():
//通过构造Wrapper条件查询一条数据
QueryWrapper<User> queryWrapper= new QueryWrapper<>();
queryWrapper.select("id","name");//设置查询字段:仅查询name id字段
queryWrapper.eq("id",5);//添加查询条件
User user1=userMapper.selectOne(queryWrapper);
System.out.println(user1);
11.selectBatchIds():
//根据id进行批量查询
List<User> userList = userMapper.selectBatchIds(Arrays.asList(5,6,7));
12.selectList():
//通过Wrapper组装查询条件,查询全部数据
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.select("id","name");//设置查询字段:仅查询name id字段
queryWrapper.eq("age",10);//添加查询条件
List<User> users =userMapper.selectList(queryWrapper);
13.selectByMap():
//根据column设置查询条件
Map<String,Object> colMap =new HashMap<>();
colMap.put("name","xx");
colMap.put("age",11);
//select * from user where name='xx' and age=11
List<User> userList1 = userMapper.selectByMap(colMap);
14.selectCount():
//根据Wrapper条件,查询记录总数
QueryWrapper<User> queryWrapper =new QueryWrapper<>();
queryWrapper.eq("name","xx").eq("age",10);
long count =userMapper.selectCount(queryWrapper);//获取总数量
15.selectPage():
//mapper层分页查询
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age",30);
Page<User> page=new Page<>(2,10);//查询第二页,每页十条数据
page =userMapper.selectPage(page,queryWrapper);
System.out.println("总共查询出:"+page.getTotal());
System.out.println("总共多少页:"+page.getPages());
System.out.println("当前第几页:"+page.getCurrent());
//获取当前页数据
List<User> users=page.getRecords();
users.forEach(System.out::println);
五、IService接口
IService是Mybatis-plus中的一个接口,它定义了一套通用的数据库操作方法,包括IService是Mybatis-plus中的一个接口,它定义了一套通用的数据库操作方法,包括常见的增删改查等操作,其底层的实现也是调用的BaseMapper。
IService接口主要用于业务逻辑层的操作,它提供了一些通用的增删改查方法,例如selectById、insert、updateById等。这些方法内部实际上也是通过调用对应的BaseMapper接口的方法来实现的。
而BaseMapper接口则主要用于数据访问层的操作,它提供了一些基本的CRUD操作方法,例如selectList、insert、delete等。这些方法可以直接操作数据库,而不需要经过业务逻辑层的处理。
因此,在使用Mybatis-plus时,我们通常会先定义一个继承自BaseMapper的Mapper接口,然后再定义一个继承自IService的服务类,让服务类去调用Mapper接口中的方法来完成具体的业务逻辑操作。这样可以使代码更加清晰、易于维护。
用法:
@Service
public interface UserService extends IService<User> {
}
1.save():
//插入操作
User user=new User();
user.setAge(10);
boolean isSuccess =userService.save(user);
2.saveBath():
//批量插入
List<User> userList=new ArrayList<>();
for (int i = 1; i < 5; i++) {
User user1=new User();
user1.setAge(10);
userList.add(user1);
}
//伪批量插入,分次数一条一条插入即insert into user values();insert....
boolean isSuccess=userService.saveBatch(userList);
3.saveOrUpdateBatch():
//批量保存或者更新
List<User> userList=new ArrayList<>();
for (int i = 1; i < 5; i++) {
User user1=new User();
user1.setAge(10);
userList.add(user1);
}
boolean isSuccess=userService.saveOrUpdateBatch(userList);//TableId 注解存在更新记录,否插入一条记录
System.out.println("返回结果:"+isSuccess);
4.update():
//通过wrapper进行更新
UpdateWrapper<User> userUpdateWrapper=new UpdateWrapper<>();
userUpdateWrapper.set("name","xi");//修改值
userUpdateWrapper.eq("id",5).eq("age",10);//条件
userService.update(userUpdateWrapper);
5.getById():
//根据id获取数据
User user=userService.getById(10);//根据id获取数据
System.out.println(user);
6.getOne():
//通过Wrapper条件查询一条数据,当结果出现多条数据时会抛出异常
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name","xx").eq("id",5);
//select * from user where name='xx' and id=5
User user=userService.getOne(queryWrapper);
7.list():
//通过List开头的方法查询多条数据
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name","xx");
List<User> userList = userService.list(queryWrapper);
8.listByIds():
//根据id列表查询数据
select * from user where id in(1,2,3,4,5);
List<User> userList1 =userService.listByIds(Arrays.asList(1,2,3,4,5));
9.listByMap():
//通过map构造查询条件
Map<String ,Object> colMap=new HashMap<>();
colMap.put("name","xx");
colMap.put("age",11);
List<User> users=userService.listByMap(colMap);
10.count():
//获取查询总数
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name","小明");
userService.count(queryWrapper);
12.page():
//service层分页查询
QueryWrapper queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age",20);
Page<User> page=new Page<>(2,10);//查询第二页,每页十条数据
page=userService.page(page,queryWrapper);
System.out.println("总共查询出:"+page.getTotal());
System.out.println("总共多少页:"+page.getPages());
System.out.println("当前第几页:"+page.getCurrent());
//获取当前页数据
List<User> users=page.getRecords();
users.forEach(System.out::println);
六、多表关联查询
多表关联查询
需求:假设前端需要展示数据:订单号、商品名称、商品价格、下单用户名、下单时间
Sql语句:select o.order_id,o.user_id,o.goods_name,o.price,u.name,u.age from t_order as o left join t_user as u on o.user_id=u.id ;
VO(Value Object)- 值对象
VO是一种用于封装数据的简单Java对象,通常用于在不同层之间传递数据。VO对象通常只包含属性和对应的getter和setter方法,用于存储和获取数据。VO的设计目标是提供一种轻量级的数据传输方式,避免数据在不同层之间频繁转换的开销。
1.创建VO层
@Data
public class OrderVo {
private Long orderId;
private Long userId;
private String goodsName;
private BigDecimal goodsPrice;
private String userName;
private Integer userAge;
}
2.在UserMapper接口中创建自定义的数据库操作方法
public interface UserMapper extends BaseMapper<User> {
//查询订单列表
List<OrderVo> selectOrders();
}
3.在Mybatis-plus配置文件中指定映射文件路径
mybatis-plus:
mapper-locations: classpath:/mapper/*Mapper.xml
4.在Resource下面添加包mapper,包下添加UserMapper.xml文件
5.写入映射和自定义的数据库操作
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.cqgcxy.mapper.UserMapper">
<resultMap id="orderMap" type="com.cqgcxy.entity.OrderVo">
<result property="userName" column="name"/>
<result property="userAge" column="age"/>
<result property="orderId" column="order_id"/>
<result property="userId" column="user_id"/>
<result property="goodsName" column="goods_name"/>
<result property="goodsPrice" column="goods_price"/>
</resultMap>
<select id="selectOrders" resultMap="orderMap">
select o.order_id,o.user_id,o.goods_name,o.price,u.name,u.age from t_order as o left join t_user as u on o.user_id=u.id
</select>
</mapper>
其中 resultMap定义了一个名为orderMap的结果映射,它将数据库表查询出的列映射到OrderVo类中的属性 ,
6.在测试类中实现
List<OrderVo> orderVos=userMapper.selectOrders();
orderVos.forEach(System.out::println);
七、关联分页查询
在上面的关联查询基础上进行分页
Sql语句:select o.order_id,o.user_id,o.goods_name,o.price,u.name,u.age from t_order as o left join t_user as u on o.user_id=u.id ${ew.customSqlSegment}
1.在UserMapper接口中创建自定义的数据库操作方法
public interface UserMapper extends BaseMapper<User> {
//关联分页查询
IPage<OrderVo> selectOrderPage(IPage<OrderVo> Page, @Param(Constants.WRAPPER) QueryWrapper<OrderVo> queryWrapper);
}
2.写入自定义的数据库操作
<select id="selectOrderPage" resultMap="orderMap">
select o.order_id,o.user_id,o.goods_name,o.price,u.name,u.age from t_order as o left join t_user as u
on o.user_id=u.id ${ew.customSqlSegment}
</select>
其中 包含一个自定义的SQL片段(${ew.customSqlSegment})。这个自定义的SQL片段可以在运行时动态地添加到查询语句中,以便实现分页功能。
3.在测试类中实现
//查询第一页,每页数据显示10条
Page<OrderVo> page=new Page<>(1,10);
//手动关闭sql优化,不然查询总数的时候只会查询主表
page.setOptimizeCountSql(false);
//组装查询条件 age=30
QueryWrapper queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age",30);
IPage<OrderVo> page1=userMapper.selectOrderPage(page,queryWrapper);
System.out.println("总条数:"+page1.getTotal());
System.out.println("总页数:"+page1.getPages());
System.out.println("当前页数:"+page1.getCurrent());
System.out.println("查询数据:"+page1.getRecords());
的SQL片段可以在运行时动态地添加到查询语句中,以便实现分页功能。
3.在测试类中实现
//查询第一页,每页数据显示10条
Page<OrderVo> page=new Page<>(1,10);
//手动关闭sql优化,不然查询总数的时候只会查询主表
page.setOptimizeCountSql(false);
//组装查询条件 age=30
QueryWrapper queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age",30);
IPage<OrderVo> page1=userMapper.selectOrderPage(page,queryWrapper);
System.out.println("总条数:"+page1.getTotal());
System.out.println("总页数:"+page1.getPages());
System.out.println("当前页数:"+page1.getCurrent());
System.out.println("查询数据:"+page1.getRecords());