char与varchar都是用来存储字符串的,但他们保存和检索的方式不同
char属于固定长度
的字符类型,varchar属于可变长度
的字符类型。
char是固定长度的,所以它的处理
速度比varchar快得多
,但是其缺点是浪费存储空间
。对于长度变化不大并且对查询速度有较高要求
的数据可以考虑使用char类型来存储。
在保存较大文本时,通常会使用text或者blob。二者之间的主要差别是
blob能用来保存二进制数据
,text只能保存字符数据
。
删除操作时(delete):MySQL
并不会回收这条记录
占据的存储空间以及索引位,而是空在那里
,等待新的数据来弥补
这个空洞。若一时半会没有数据来填补这个空洞,就会形成资源浪费。
Blob和Text值因为占据大量空间
,特别是在执行了大量的删除
操作时,如果不采取操作一定会造成性能问题。
因此存在Blob或者Text等占大量空间的表,当执行大量删除操作的时候建议定期使用OPTIMIZE TABLE
功能对这类表进行碎片整理,避免因为“空洞”导致性能问题。
查询的时候(select):使用select * 就不是很好的操作,会遍历大量数据,造成性能问题。最好用的时候查,不用的时候不用查。
如果优化的话,建议将这些Blob的数据,都放到一张表中
,例如文件表,这样哪怕业务表select * 也无所谓了。
@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
字段。
@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策略表示不指定主键生成策略
,所以这个注释加不加无所谓
直接定义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 {
@Test
public void aInsert() {
User user = new User();
user.setName("咩咩");
user.setAge(5);
user.setEmail("miemie@mp.com");
Assert.assertTrue(user.insert());
// 成功可以直接获取 ID
System.err.println("\n插入成功 ID 为:" + user.toString());
}
@Test
public 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));
}
@Test
public 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)));
}
// 使用lambdaQuery
LambdaQueryWrapper<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
LambdaQueryChainWrapper有以下方法获取数据:
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的用法
@Test
public void testQueryWrapper() {
// 查询条件构造器
QueryWrapper<BannerItem> wrapper = new QueryWrapper<>();
wrapper.eq("banner_id", id);
// 查询操作
List<BannerItem> bannerItems = bannerItemMapper.selectList(wrapper)
}
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();
在 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 层的方法来执行。
QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().
eq("attr_id",key).
eq("catelog_id",catelogId);
QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().
eq("attr_id",key).
or().
eq("catelog_id",catelogId);
SELECT
*
FROM project
WHERE
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
*
FROM
employee_project
WHERE
state IS NOT NULL
AND flag = 1
AND (
under_project_time IS NULL
OR 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')")));
SELECT
*
FROM
customer
WHERE
taxpayer_identification_number = '912102113000000000'
AND (
parent_id = 111
OR contact_number = '88'
)
AND NAME = '啦啦啦'
OR number <> 1
AND 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));
//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();
//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();
//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();
// 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();
// 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(value = "myCache", key = "#id")
public void deleteById(Long id) {
// 删除操作
}
我们定义了一个 deleteById 方法,它用于删除指定 id 的数据。在方法上使用了 @CacheEvict 注解,表示在删除操作执行后清空名为 myCache 的缓存中的 key 为 id 的缓存数据。