后端杂七杂八系列篇一
- ① MySQL选择合适的数据类型
- ① Char与Varchar
- ② Text与Blob
- ② @EqualsAndHashCode(callSuper = true)的作用
- ③ mybatis-plus 相关
- ① 主键生成策略
- ② 使用Model实现CRUD
- ③ Wrapper的用法
- ① Wrapper的继承关系
- ② 项目中最常用的warpper [LambdaQueryWrapper]
- ③ 项目中第二常用的warpper [LambdaQueryChainWrapper]
- ③ Java 中的lambdaQuery()
- ④ and 和 or的用法(Wrapper)
- ① where A=? and B=? 形式
- ② where A=? or B=? 形式
- ③ where A=? and (B...)
- ④ where A=? and (B...) or C
- ⑤ and 和 or的用法(lambdaQuery())
- where A=? and B=?
- where A=? or B=?
- where A=? or(C=? and D=?)
- where (A=?andB=?)or(C=?andD=?)
- whert A =? or (B=? and ( C=? or D=?))
- ④ @CacheEvict 注解
① MySQL选择合适的数据类型
① Char与Varchar
char与varchar都是用来存储字符串的,但他们保存和检索的方式不同
char属于固定长度
的字符类型,varchar属于可变长度
的字符类型。
char是固定长度的,所以它的处理
速度比varchar快得多
,但是其缺点是浪费存储空间
。对于长度变化不大并且对查询速度有较高要求
的数据可以考虑使用char类型来存储。
② Text与Blob
在保存较大文本时,通常会使用text或者blob。二者之间的主要差别是
blob能用来保存二进制数据
,text只能保存字符数据
。
删除操作时(delete):MySQL
并不会回收这条记录
占据的存储空间以及索引位,而是空在那里
,等待新的数据来弥补
这个空洞。若一时半会没有数据来填补这个空洞,就会形成资源浪费。
Blob和Text值因为占据大量空间
,特别是在执行了大量的删除
操作时,如果不采取操作一定会造成性能问题。
因此存在Blob或者Text等占大量空间的表,当执行大量删除操作的时候建议定期使用OPTIMIZE TABLE
功能对这类表进行碎片整理,避免因为“空洞”导致性能问题。
查询的时候(select):使用select * 就不是很好的操作,会遍历大量数据,造成性能问题。最好用的时候查,不用的时候不用查。
如果优化的话,建议将这些Blob的数据,都放到一张表中
,例如文件表,这样哪怕业务表select * 也无所谓了。
② @EqualsAndHashCode(callSuper = true)的作用
@EqualsAndHashCode是java的自带的注解,通常用于在
子类中自动生成 equals 和 hashCode
方法,同时考虑到了父类的成员变量
。
class Person {private String name;private int age;
}@EqualsAndHashCode(callSuper = true)
class Student extends Person {private int studentId;
}
如果你使用了
@EqualsAndHashCode(callSuper = true)
,那么在生成 equals 和 hashCode 方法时,会考虑到Person 类中的 name 和 age
字段。
如果你使用了@EqualsAndHashCode(callSuper = false)
,只会考虑studentId
字段。
③ mybatis-plus 相关
① 主键生成策略
@TableId , 该注解提供了各种的主键生成策略
自动生成策略(AUTO策略)
@TableId(value=“id”,type = IdType.AUTO) // value:指定的是表中主键名称。
跟随数据库表的主键递增策略
,前提是数据库表的主键要设置为自增。
INPUT策略
@TableId(type = IdType.INPUT)
需要 我们手动的插入id
ASSIGN_ID策略(使用雪花算法生成)
@TableId(type = IdType.ASSIGN_ID)
由雪花算法,生成Long 类型的id
ASSIGN_UUID策略(使用uuid生成主键)
@TableId(type = IdType.ASSIGN_ID)
由UUID的编码规则,生成String 类型的id
NONE策略(不指定主键生成策略)
@TableId(type = IdType.NONE)
NONE策略表示不指定主键生成策略
,所以这个注释加不加无所谓
② 使用Model实现CRUD
直接定义Bean的时候实现Model类,该类的作用是能
通过实体
直接进行crud操作
,而不需要进行调用dao
。
前提是“必须存在对应的原始mapper并继承baseMapper
并且可以使用的前提下”。
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
public class User extends Model<User> {private Long id;private String name;private Integer age;private String email;
}
//前提:必须写入mapper
public interface UserMapper extends BaseMapper<User> {}
Model类 自身实现了 insert() ,insertOrUpdate(),deleteById(Serializable id),deleteById() ,delete(Wrapper queryWrapper),updateById(),update(Wrapper updateWrapper),selectAll(),selectList(Wrapper queryWrapper),selectOne(Wrapper queryWrapper),selectPage(E page, Wrapper queryWrapper),selectCount(Wrapper queryWrapper)
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {@Testpublic void aInsert() {User user = new User();user.setName("咩咩");user.setAge(5);user.setEmail("miemie@mp.com");Assert.assertTrue(user.insert());// 成功可以直接获取 IDSystem.err.println("\n插入成功 ID 为:" + user.toString());}@Testpublic void bDelete() {Assert.assertTrue(new User().setId(3L).deleteById());Assert.assertTrue(new User().delete(new QueryWrapper<User>().lambda().eq(User::getName, "Sandy")));List<User> userList=new User().selectAll();userList.forEach(u->System.out.print(u));}@Testpublic void cUpdate() {Assert.assertTrue(new User().setId(1L).setEmail("ab@c.c").updateById());Assert.assertTrue(new User().update(new UpdateWrapper<User>().lambda().set(User::getAge, 3).eq(User::getId, 2)));}
③ Wrapper的用法
① Wrapper的继承关系
② 项目中最常用的warpper [LambdaQueryWrapper]
// 使用lambdaQueryLambdaQueryWrapper<SysDroneInfo> wrapper = Wrappers.lambdaQuery();// 无人机名称if (StrUtil.isNotBlank(sysDroneInfo.getDroneName())) {wrapper.eq(SysDroneInfo::getDroneName, sysDroneInfo.getDroneName());}// 无人机型号if (StrUtil.isNotBlank(sysDroneInfo.getDroneManufacturer())) {wrapper.eq(SysDroneInfo::getDroneManufacturer, sysDroneInfo.getDroneManufacturer());}// 无人机状态if (StrUtil.isNotBlank(sysDroneInfo.getStatus())) {wrapper.eq(SysDroneInfo::getStatus, sysDroneInfo.getStatus());}return baseMapper.selectPage(page, wrapper);
LambdaQueryWrapper<MerchantApply> lambdaQueryWrapper = new LambdaQueryWrapper();lambdaQueryWrapper.eq(MerchantApply::getStatus, MerchantApplyEnums.STATUS.CONFIRM.getCode()).eq(MerchantApply::getIsDelete, MerchantApplyEnums.DEL_FLAG.NOT_DELETE.getCode()).and(wrapper ->{wrapper.eq(MerchantApply::getUniscid, uniscid).or().eq(MerchantApply::getApplicant, merchantInformation.getCreateBy());}).last("limit 1");
(status = ? AND is_delete = ? AND (uniscid = ? OR applicant = ?)) limit 1
③ 项目中第二常用的warpper [LambdaQueryChainWrapper]
LambdaQueryChainWrapper有以下方法获取数据:
- page():分页
list()
:列表(常用)
one()
:获取1个。若有多个结果,则报异常。此方法只用于只有一个结果的情况。(最常用)
List<BannerItem> bannerItems = new LambdaQueryChainWrapper<>(bannerItemMapper).eq(BannerItem::getBannerId, id).list();
BannerItem bannerItem = new LambdaQueryChainWrapper<>(bannerItemMapper).eq(BannerItem::getId, id).one();
QuryWrapper的用法
@Testpublic void testQueryWrapper() {// 查询条件构造器QueryWrapper<BannerItem> wrapper = new QueryWrapper<>();wrapper.eq("banner_id", id);// 查询操作List<BannerItem> bannerItems = bannerItemMapper.selectList(wrapper)}
③ Java 中的lambdaQuery()
Lambda 查询条件是通过 Java 的 lambda 表达式来构建的,它提供了更加灵活和可读性更高的查询条件构建方式。Lambda 查询条件可以与实体类中的属性进行绑定,并且能够自动推断属性类型,减少了代码的冗余。
lambdaQuery() 方法与MybatisPlus中的 wrapper 并不是直接等价的,但它们都用于构建查询条件。
//SELECT id,name,age,sex FROM student WHERE (name = ? AND age = ?)
List<Student> list = studentService.lambdaQuery().eq(Student::getName, "1").eq(Student::getAge, 1).list();
lambdaQuery和MP对应关系
④ and 和 or的用法(Wrapper)
在 MybatisPlus 中,and() 和or() 方法是一个常用的链式调用方法,用于
构建复杂的查询条件
。它接受一个参数,通常是 Lambda 表达式
或者其他的条件构造器,用于进一步定义查询条件。
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.and(i -> i.eq(User::getName, "John").like(User::getEmail, "example@email.com"));
List<User> users = userService.list(queryWrapper);
在上面的示例中,and() 方法传入了三个参数,分别代表年龄等于20、状态不等于0和地址模糊匹配 “street”。
需要注意的是,and() 方法只是用于组合多个查询条件
,它本身并不执行查询操作
。最终的查询操作需要调用相应的 Mapper 或 Service 层的方法来执行。
① where A=? and B=? 形式
QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().
eq("attr_id",key).
eq("catelog_id",catelogId);
② where A=? or B=? 形式
QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().
eq("attr_id",key).
or().
eq("catelog_id",catelogId);
③ where A=? and (B…)
SELECT*FROM projectWHERE type = 1 AND (DATE_FORMAT(create_time, '%Y-%m') <= '2022-01');
projectMapper.selectList(new LambdaQueryWrapper<Project>().eq(Project::getType,1).and(qw -> qw.apply("DATE_FORMAT(create_time, '%Y-%m') <= '" + dateStr + "'")));
SELECT
*
FROMemployee_project
WHEREstate IS NOT NULLAND flag = 1AND (under_project_time IS NULLOR DATE_FORMAT(under_project_time, '%Y-%m-%d') >= '2022-07-27');
employeeProjectMapper.selectList(new LambdaQueryWrapper<EmployeeProject>().isNotNull(EmployeeProject::getState).eq(EmployeeProject::getFlag, 1).and(qw -> qw.isNull(EmployeeProject::getUnderProjectTime).or().apply("DATE_FORMAT(under_project_time, '%Y-%m-%d') >= DATE_FORMAT(NOW(),'%Y-%m-%d')")));
④ where A=? and (B…) or C
SELECT
*
FROMcustomer
WHEREtaxpayer_identification_number = '912102113000000000'AND (parent_id = 111OR contact_number = '88')AND NAME = '啦啦啦'OR number <> 1AND company_type = 1;
// 示例二
customerMapper.selectList(new LambdaQueryWrapper<Customer>().eq(Customer::getTaxpayerIdentificationNumber,"912102113000000000").and(qw -> qw.eq(Customer::getParentId,111).or().eq(Customer::getContactNumber,"88")).eq(Customer::getName, "啦啦啦").or().ne(Customer::getNumber, 1).eq(Customer::getCompanyType,1));
⑤ and 和 or的用法(lambdaQuery())
where A=? and B=?
//SELECT id,name,age,sex FROM student WHERE (name = ? AND age = ?)
List<Student> list = studentService.lambdaQuery().eq(Student::getName, "1").eq(Student::getAge, 1).list();
where A=? or B=?
//SELECT id,name,age,sex FROM student WHERE (name = ? OR age = ?)
List<Student> list = studentService.lambdaQuery().eq(Student::getName, "1").or().eq(Student::getAge, 12).list();
where A=? or(C=? and D=?)
//SELECT id,name,age,sex FROM student WHERE (name = ? OR (name = ? AND age = ?))
List<Student> list =studentService.lambdaQuery().eq(Student::getName, "1").or(wp -> wp.eq(Student::getName, "1").eq(Student::getAge, 12)).list();
where (A=?andB=?)or(C=?andD=?)
// SELECT id,name,age,sex FROM student WHERE ((name = ? AND age = ?) OR (name = ? AND age = ?))
List<Student> list =studentService.lambdaQuery().and(wp -> wp.eq(Student::getName, "1").eq(Student::getAge, 12)).or(wp -> wp.eq(Student::getName, "1").eq(Student::getAge, 12)).list();
whert A =? or (B=? and ( C=? or D=?))
// SELECT * FROM student WHERE ((name <> 1) OR (name = 1 AND (age IS NULL OR age >= 11)))
List<Student> list =studentService.lambdaQuery().and(wp -> wp.ne(Student::getName, "1")).or(wp ->wp.eq(Student::getName, "1").and(wpp -> wpp.isNull(Student::getAge).or().ge(Student::getAge, 11))).list();
④ @CacheEvict 注解
@CacheEvict 注解用于清空缓存。
@CacheEvict(value = "myCache", key = "#id")
public void deleteById(Long id) {// 删除操作
}
我们定义了一个 deleteById 方法,它用于删除指定 id 的数据。在方法上使用了 @CacheEvict 注解,表示在删除操作执行后清空名为 myCache 的缓存中的 key 为 id 的缓存数据。