4.1.3 ID生成策略对比
介绍了这些主键ID的生成策略,我们以后该用哪个呢?
-
NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂
-
AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用
-
ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢
-
ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键
-
综上所述,每一种主键策略都有自己的优缺点,根据自己项目业务的实际情况来选择使用才是最明智的选择。
4.1.4 简化配置
前面我们已经完成了表关系映射、数据库主键策略的设置,接下来对于这两个内容的使用,我们再讲下他们的简化配置:
模型类主键策略设置
对于主键ID的策略已经介绍完,但是如果要在项目中的每一个模型类上都需要使用相同的生成策略,如:
确实是稍微有点繁琐,我们能不能在某一处进行配置,就能让所有的模型类都可以使用该主键ID策略呢?
答案是肯定有,我们只需要在配置文件中添加如下内容:
mybatis-plus: global-config: db-config: id-type: assign_id
配置完成后,每个模型类的主键ID策略都将成为assign_id.
数据库表与模型类的映射关系
MP会默认将模型类的类名名首字母小写作为表名使用,假如数据库表的名称都以tbl_
开头,那么我们就需要将所有的模型类上添加@TableName
,如:
配置起来还是比较繁琐,简化方式为在配置文件中配置如下内容:
mybatis-plus: global-config: db-config: table-prefix: tbl_
设置表的前缀内容,这样MP就会拿 tbl_
加上模型类的首字母小写,就刚好组装成数据库的表名。
4.2 多记录操作
先来看下问题:
之前添加了很多商品到购物车,过了几天发现这些东西又不想要了,该怎么办呢?
很简单删除掉,但是一个个删除的话还是比较慢和费事的,所以一般会给用户一个批量操作,也就是前面有一个复选框,用户一次可以勾选多个也可以进行全选,然后删一次就可以将购物车清空,这个就需要用到批量删除
的操作了。
具体该如何实现多条删除,我们找找对应的API方法
int deleteBatchIds( (Constants.COLLECTION) Collection<? extends Serializable> idList);
翻译方法的字面意思为:删除(根据ID 批量删除),参数是一个集合,可以存放多个id值。
需求:根据传入的id集合将数据库表中的数据删除掉。
@SpringBootTest class Mybatisplus03DqlApplicationTests { @Autowired private UserDao userDao; @Test void testDelete(){ //删除指定多条数据 List<Long> list = new ArrayList<>(); list.add(1402551342481838081L); list.add(1402553134049501186L); list.add(1402553619611430913L); userDao.deleteBatchIds(list); } }
执行成功后,数据库表中的数据就会按照指定的id进行删除。
除了按照id集合进行批量删除,也可以按照id集合进行批量查询,还是先来看下API
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
方法名称翻译为:查询(根据ID 批量查询),参数是一个集合,可以存放多个id值。
需求:根据传入的ID集合查询用户信息.
@SpringBootTest class Mybatisplus03DqlApplicationTests { @Autowired private UserDao userDao; @Test void testGetByIds(){ //查询指定多条数据 List<Long> list = new ArrayList<>(); list.add(1L); list.add(3L); list.add(4L); userDao.selectBatchIds(list); } }查询结果就会按照指定传入的id值进行查询
4.3 逻辑删除
接下来要讲解是删除中比较重要的一个操作,逻辑删除,先来分析下问题:
接下来要讲解是删除中比较重要的一个操作,逻辑删除,先来分析下问题:
员工ID为1的张业绩,总共签了三个合同,如果此时他离职了,我们需要将员工表中的数据进行删除,会执行delete操作
如果只删除员工不删除合同表数据,那么合同的员工编号对应的员工信息不存在,那么就会出现垃圾数据,就会出现无主合同,根本不知道有张业绩这个人的存在
区分的方式,就是在员工表中添加一列数据
deleted
,如果为0说明在职员工,如果离职则将其改完1,(0和1所代表的含义是可以自定义的)所以对于删除操作业务问题来说有:
物理删除:业务数据从数据库中丢弃,执行的是delete操作
逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中,执行的是update操作MP中逻辑删除具体该如何实现?
步骤1:修改数据库表添加deleted
列
字段名可以任意,内容也可以自定义,比如0
代表正常,1
0
正常。
步骤2:实体类添加属性
(1)添加与数据库表的列对应的一个属性名,名称可以任意,如果和数据表列名对不上,可以使用@TableField进行关系映射,如果一致,则会自动对应。
(2)标识新增的字段为逻辑删除字段,使用@TableLogic
@Data //@TableName("tbl_user") 可以不写是因为配置了全局配置 public class User { @TableId(type = IdType.ASSIGN_UUID) private String id; private String name; @TableField(value="pwd",select=false) private String password; private Integer age; private String tel; @TableField(exist=false) private Integer online; @TableLogic(value="0",delval="1") //value为正常数据的值,delval为删除数据的值 private Integer deleted; }
步骤3:运行删除方法
@SpringBootTest class Mybatisplus03DqlApplicationTests { @Autowired private UserDao userDao; @Test void testDelete(){ userDao.deleteById(1L); } }
从测试结果来看,逻辑删除最后走的是update操作,会将指定的字段修改成删除状态对应的值。
思考
逻辑删除,对查询有没有影响呢?
-
执行查询操作
-
@SpringBootTest class Mybatisplus03DqlApplicationTests { @Autowired private UserDao userDao; @Test void testFind(){ System.out.println(userDao.selectList(null)); } }
运行测试,会发现打印出来的sql语句中会多一个查询条件,如:
-
-
-
@Mapper public interface UserDao extends BaseMapper<User> { //查询所有数据包含已经被删除的数据 @Select("select * from tbl_user") public List<User> selectAll(); }
@TableLogic
注解,如何优化? -
mybatis-plus: global-config: db-config: # 逻辑删除字段名 logic-delete-field: deleted # 逻辑删除字面值:未删除为0 logic-not-delete-value: 0 # 逻辑删除字面值:删除为1 logic-delete-value: 1
介绍完逻辑删除,逻辑删除的本质为:
逻辑删除的本质其实是修改操作。如果加了逻辑删除字段,查询数据时也会自动带上逻辑删除字段。
执行的SQL语句为:
UPDATE tbl_user SET ==deleted===1 where id = ? AND ==deleted===0
执行数据结果为:
-
-
名称 @TableLogic 类型 ==属性注解== 位置 模型类中用于表示删除字段的属性定义上方 作用 标识该字段为进行逻辑删除的字段 相关属性 value:逻辑未删除值
文章评论