`Mybatis Plus
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生(提供了快速使用mybatis的方式)
普通Maven项目下的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
</dependency>
SpringBoot环境下的MP(项目中使用)
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
MP提供的常用主键生成策略如下:
生成策略 | 应用场景 | 特点 |
---|---|---|
IdType.AUTO | 数据库主键自增(确保数据库设置了 主键自增 否则无效) | 1.使用数据库自带的主键自增值; 2.数据库自增的主键值会回填到实体类中; 3.数据库服务端生成的; |
IdType.ASSIGN_ID | 主键类型为number类型或数字类型String | 1.MP客户端生成的主键值; 2.生成的主键值是数字形式的字符串 3.主键对应的类型可以是数字类型或者数字类型的字符串 4.底层基于雪花算法,让数据库的唯一标识也参与id的生成运算,保证id在分布式环境下,全局唯一(避免id的主键冲突问题); |
IdType.ASSIGN_UUID | 主键类型为 string(包含数字和字母组成) | 1.生成的主键值包含数字和字母组成的字符串; 2.注意事项:如果数据库中主键值是number类型的,可不可用 |
雪花算法 |
@TableId注解作用:
1.标识实体类中主键对应属性;
2.定义主键生成策略;
@TableId使用:
添加在实体类的主键对应的成员属性上即可;
@TableField:
添加在数据库字段对应的实体类属性上
@TableName:
实体类对应相对的表名
1.通过@TableField(“表列名”) 指定映射关系
以下情况可以省略:
2.忽略某个字段的查询和插入 @TableField(exist = false)
// @TableName: 指定当前对象对应的数据库表
@TableName("tb_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
/**
* @TableId: 指定当前表的主键
* value: 建立数据库主键字段与实体字段的对应关系
* type: 设置主键生成策略,
* IdType.NONE/ASSIGN_ID:默认情况下使用雪花算法
* IdType.AUTO:使用数据库的主键自增
* ASSIGN_UUID:使用UUID生成一个全局唯一字符串
*/
@TableId(type = IdType.AUTO)
private Long id;
private String userName;
private String password;
// 建立数据库字段与实体字段的对应关系 @TableField("与数据库字段名对应")
@TableField("t_name")
private String name;
private Integer age;
// 忽略此字段
@TableField(exist = false)
private String email;
}
(1)添加@TableField注解
@TableField(fill = FieldFill.INSERT) //插入数据时进行填充(填充时机可以选择(DEFAULT,INSERT,UPDATE, INSERT_UPDATE))
private String password;
(2)编写MyMetaObjectHandler
package cn.itcast.mp.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Object password = getFieldValByName("password", metaObject);
if(null == password){
//字段为空,可以进行填充
setFieldValByName("password", "123456", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
eq( ) : 等于 =
ne( ) : 不等于 <>
gt( ) : 大于 >
ge( ) : 大于等于 >=
lt( ) : 小于 <
le( ) : 小于等于 <=
between ( ) : BETWEEN 值1 AND 值2
notBetween ( ) : NOT BETWEEN 值1 AND 值2
in( ) : in
notIn( ) :not in
sql中反向查询eg:not like != 等等,查询时是不会走索引的;
代码如下(示例):
@Test
public void testInsert(){
User user = User.builder()
.userName("qhj")
.age(23)
.password("2344")
.email("1213@qq.com").build();
int insert = userMapper.insert(user);
if(insert > 0){
System.out.println("添加成功!");
}
System.out.println(user);
}
代码如下(示例):
@Test
public void testDeleteById(){
/**
* 根据id删除用户
*/
//userMapper.deleteById(18);
/**
* 根据id批量删除
*/
/** List list = new ArrayList<>();
list.add(1);
list.add(19);
userMapper.deleteBatchIds(list);
*/
/**
* 根据map删除
*/
HashMap<String, Object> map = new HashMap<>();
map.put("password",2344);
map.put("user_name","qhj");
userMapper.deleteByMap(map);
}
@Test
public void testUpdate(){
User user = User.builder().userName("ryc").age(23).password("21324565").email("1324@qq.com").build();
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getId,"15");
int i = userMapper.update(user,queryWrapper);
System.out.println(i>0? "修改成功":"改失败");
}
/**
* LambdaQueryWrapper查询 并限定字段
*/
@Test
public void testLambda(){
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(User::getPassword,"123456")
.like(User::getUserName,"赵")
.in(User::getAge,26,28,29)
.orderByDesc(User::getAge)
.select("user_name","password","age","email");
List<User> list = userMapper.selectList(queryWrapper);
System.out.println(list);
}
/**
* 分页查询
*/
@Test
public void testPage(){
//创建分页对象
IPage<User> page= new Page<>(1,3);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age");
IPage<User> userIPage= userMapper.selectPage(page,queryWrapper);
//获取分页数据信息
List<User> list = userIPage.getRecords();
for(User user: list){
System.out.println(user);
}
long current = page.getCurrent();
System.out.println(current);
long pages = page.getPages();
System.out.println(pages);
long size = page.getSize();
System.out.println(size);
long total = page.getTotal();
System.out.println(total);
}
MybatisPlus为了开发更加快捷,对业务层也进行了封装,直接提供了相关的接口和实现类;
我们在进行业务层开发时,可以继承它提供的接口和实现类,使得编码更加高效;
1.定义一个服务扩展接口,该接口继承公共接口IService;
//在公共接口的基础上扩展
public interface UserService extends IService<User> {
}
2.定义一个服务实现类,该类继承ServiceImpl<Mapper,Entity>,并实现自定义的扩展接口;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}