当前位置: 首页 > news >正文

做网站的不足 心得商城类网站总体功能策划

做网站的不足 心得,商城类网站总体功能策划,长沙网络工程学院,做网站需要apache目录 MyBatis-Plus快速入门 简介 快速入门 MyBatis-Plus核心功能 基于Mapper接口 CRUD 对比mybatis和mybatis-plus#xff1a; CRUD方法介绍#xff1a; 基于Service接口 CRUD 对比Mapper接口CRUD区别#xff1a; 为什么要加强service层#xff1a; 使用方式 CR…目录 MyBatis-Plus快速入门 简介 快速入门 MyBatis-Plus核心功能 基于Mapper接口 CRUD 对比mybatis和mybatis-plus CRUD方法介绍 基于Service接口 CRUD 对比Mapper接口CRUD区别 为什么要加强service层 使用方式 CRUD方法介绍 分页查询实现 MyBatis和Mybatis-Plus分页查询 使用分页查询 自定义的mapper方法使用分页 条件构造器使用 1、条件构造器作用 2、条件构造器继承结构 3、基于QueryWrapper组装条件 4、基于UpdateWrapper组装条件 5、基于LambdaQueryWrapper组装条件 LambdaQueryWrapper对比QueryWrapper 6、基于LambdaUpdateWrapper组装条件 核心注解使用 TableName TableId TableField MyBatis-Plus高级拓展 逻辑删除实现 逻辑删除全局配置 乐观锁实现 场景 资源争抢的解决方法 理解点: 具体技术和方案 版本号乐观锁的实现流程 使用mybatis-plus数据使用乐观锁 防全表更新和删除实现 MyBatis-Plus代码生成器MyBatisX 插件 MyBatisX插件逆向工程 MyBatisX快速代码生成 MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/?spmwolai.workspace.0.0.330e767bDepZBf MyBatis-Plus快速入门 简介 MyBatis-PlusMP是一个MyBatis的增强工具在MyBatis的基础上做增强简化开发。 支持MySQLOracle等大部分数据库。 MyBatis-Plus的功能总的来说就是 自动生成单表的CRUD功能 提供丰富的条件拼接方法 全自动ORM类型持久层框架 全自动orm思维持久层框架如hibernate只需要把数据库数据和java实体类映射配置它就能提供crud方法而且会自动生成对应的sql语句。 MyBatis-Plus的功能仅限于单表操作多表操作还是自己写SQL比较好。 快速入门 1.准备数据库表databasemybatis_plustableuser CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT 主键ID,name VARCHAR(30) NULL DEFAULT NULL COMMENT 姓名,age INT(11) NULL DEFAULT NULL COMMENT 年龄,email VARCHAR(50) NULL DEFAULT NULL COMMENT 邮箱,PRIMARY KEY (id) );INSERT INTO user (id, name, age, email) VALUES (1, Jone, 18, test1baomidou.com), (2, Jack, 20, test2baomidou.com), (3, Tom, 28, test3baomidou.com), (4, Sandy, 21, test4baomidou.com), (5, Billie, 24, test5baomidou.com);2.创建boot工程springboot-mybatis-plus 3.导入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion3.0.5/version/parentgroupIdcom.qiu/groupIdartifactIdspringboot-mybatis-plus/artifactIdversion1.0-SNAPSHOT/versiondependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!-- 测试环境 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactId/dependency!-- mybatis-plus --dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.3.1/version/dependency!-- 数据库相关配置启动器 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependency!-- druid启动器的依赖 --dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-3-starter/artifactIdversion1.2.18/version/dependency!-- 驱动类--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.28/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.28/version/dependency/dependencies!-- SpringBoot应用打包插件--buildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project 如果druid版本在1.2.20以下会报错解决方法在之前springboot文章中 4.创建pojo类 Data public class User {private Long id;private String name;private Integer age;private String email; }5.创建mapper接口并继承mybatis-plus提供的Mapper接口此接口下自带crud方法 public interface UserMapper extends BaseMapperUser { }6.编写测试类进行测试导入了spring-boot-starter-test启动器只需要在测试类添加SpringBootTest就可以直接注入组件 SpringBootTest//springboot下测试环境注解 public class BootTest {Autowiredprivate UserMapper userMapper;Testpublic void query(){ListUser users userMapper.selectList(null);System.out.println(users users);} } 注意使用注解时测试类要和启动类在同一目录结构下 7.测试结果 MyBatis-Plus核心功能 基于Mapper接口 CRUD 对比mybatis和mybatis-plus mybatis对数据库的操作1.创建mapper接口定义crud方法 2.创建mapperxml编写crud的sql mybatis-plus对数据库的操作1.创建mapper接口继承BaseMapperT 2.原来的mybatis操作没有变需要时依然可以使用 BaseMapper中的方法。 public interface BaseMapperT extends MapperT {int insert(T entity);int deleteById(Serializable id);int deleteById(T entity);int deleteByMap(Param(cm) MapString, Object columnMap);int delete(Param(ew) WrapperT queryWrapper);int deleteBatchIds(Param(coll) Collection? idList);int updateById(Param(et) T entity);int update(Param(et) T entity, Param(ew) WrapperT updateWrapper);T selectById(Serializable id);ListT selectBatchIds(Param(coll) Collection? extends Serializable idList);ListT selectByMap(Param(cm) MapString, Object columnMap);default T selectOne(Param(ew) WrapperT queryWrapper) {ListT list this.selectList(queryWrapper);if (list.size() 1) {return list.get(0);} else if (list.size() 1) {throw new TooManyResultsException(Expected one result (or null) to be returned by selectOne(), but found: list.size());} else {return null;}}default boolean exists(WrapperT queryWrapper) {Long count this.selectCount(queryWrapper);return null ! count count 0L;}Long selectCount(Param(ew) WrapperT queryWrapper);ListT selectList(Param(ew) WrapperT queryWrapper);ListMapString, Object selectMaps(Param(ew) WrapperT queryWrapper);ListObject selectObjs(Param(ew) WrapperT queryWrapper);P extends IPageT P selectPage(P page, Param(ew) WrapperT queryWrapper);P extends IPageMapString, Object P selectMapsPage(P page, Param(ew) WrapperT queryWrapper); } CRUD方法介绍 application.yaml mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台输出日志#像驼峰映射的操作在底层已经设置了好了可以不修改。 mapper接口 public interface UserMapper extends BaseMapperUser { }测试 SpringBootTest//springboot下测试环境注解 public class BootTest {Autowiredprivate UserMapper userMapper; // ------------------------------------------------------- // | id | name | age | email | // ------------------------------------------------------- // | 1 | Jone | 18 | test1baomidou.com | // | 2 | Jack | 20 | test2baomidou.com | // | 3 | Tom | 28 | test3baomidou.com | // | 4 | Sandy | 21 | test4baomidou.com | // | 5 | Billie | 24 | test5baomidou.com | // | 1767361818149871618 | 123 | 88 | 11 | // -------------------------------------------------------Test // INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) // 1767362650761154561(Long), 123(String), 88(Integer), 11(String) // mybatis-plus会自动对id进行赋值。public void test_insert(){User user new User();user.setAge(88);user.setEmail(11);user.setName(123);userMapper.insert(user);} // ------------------------------------------------------- // | id | name | age | email | // ------------------------------------------------------- // | 1 | Jone | 18 | test1baomidou.com | // | 2 | Jack | 20 | test2baomidou.com | // | 3 | Tom | 28 | test3baomidou.com | // | 4 | Sandy | 21 | test4baomidou.com | // | 5 | Billie | 24 | test5baomidou.com | // | 1767361818149871618 | 123 | 88 | 11 | // | 1767362650761154561 | 123 | 88 | 11 | // -------------------------------------------------------Testpublic void test_delete(){//根据id删除 // DELETE FROM user WHERE id? // 1767362650761154561(Long)userMapper.deleteById(1767362650761154561L);//根据age20和namejack // DELETE FROM user WHERE name ? AND age ? // jack(String), 20(Integer)Map mapnew HashMap();map.put(age,20);map.put(name,jack);userMapper.deleteByMap(map);} // ------------------------------------------------------- // | id | name | age | email | // ------------------------------------------------------- // | 1 | Jone | 18 | test1baomidou.com | // | 3 | Tom | 28 | test3baomidou.com | // | 4 | Sandy | 21 | test4baomidou.com | // | 5 | Billie | 24 | test5baomidou.com | // | 1767361818149871618 | 123 | 88 | 11 | // -------------------------------------------------------Testpublic void test_update(){//根据id修改//user的id必须有值//如果setXxx(null)不进行修改,这就是为什么要把age设置为Integer包装类因为int类型默认为0 // UPDATE user SET age? WHERE id? // 99(Integer), 1(Long)User user new User();user.setId(1L);user.setName(null);user.setAge(99);userMapper.updateById(user);//将所有人的年龄改为Name改为111//如果setXxx(null)不进行修改 // UPDATE user SET name? // 111(String)User user1 new User();user1.setName(111);user1.setEmail(null);userMapper.update(user1,null);} // ----------------------------------------------------- // | id | name | age | email | // ----------------------------------------------------- // | 1 | 111 | 99 | test1baomidou.com | // | 3 | 111 | 28 | test3baomidou.com | // | 4 | 111 | 21 | test4baomidou.com | // | 5 | 111 | 24 | test5baomidou.com | // | 1767361818149871618 | 111 | 88 | 11 | // -----------------------------------------------------Testpublic void test_select(){//根据id查询 // SELECT id,name,age,email FROM user WHERE id? // 1(Long) // user User(id1, name111, age99, emailtest1baomidou.com)User user userMapper.selectById(1L);System.out.println(user user);//集合查询 // SELECT id,name,age,email FROM user WHERE id IN ( ? , ? ) // 1(Long), 3(Long) // users [User(id1, name111, age99, emailtest1baomidou.com), // User(id3, name111, age28, emailtest3baomidou.com)]ListLong ids new ArrayList();ids.add(1L);ids.add(3L);ListUser users userMapper.selectBatchIds(ids);System.out.println(users users);} 基于Service接口 CRUD 对比Mapper接口CRUD区别 1.service层的加强进一步封装了crud采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆并且支持批量操作 2.service层的方法自动添加事务 为什么要加强service层 1.如果接收的请求是查询用户信息那么service层的操作仅仅只是调用了mapper的select方法。 2.如果controller层接收的请求较简单插入单表数据查询单表数据等可以直接调用service层加强的方法不需要在从service层调用mapper层方法。 3.加强service后简单逻辑走service复杂逻辑再走mapper 使用方式 接口继承IServiceT接口 public interface UserService extends IServiceUser { }实现类继承 ServiceImplM extends BaseMapperT, T  public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { } 为什么既要继承接口又要继承实现类 IServiceT接口中定义了所有方法但只默认实现了一半而ServiceImplM extends BaseMapperT, T中实现了另一半如果不继承实现类需要自己手动实现另一半方法。ServiceImpl 实现了 IService public class ServiceImplM extends BaseMapperT, T implements IServiceT {…… } CRUD方法介绍 package com.qiu;import com.qiu.pojo.User; import com.qiu.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;import java.util.ArrayList; import java.util.List;SpringBootTest public class BootUserTest2 {Autowiredprivate UserService userService;// 保存Testpublic void test_save(){ListUser list new ArrayList();User usernew User();user.setAge(18);user.setEmail(666);user.setName(123);list.add(user);User user1new User();user1.setAge(23);user1.setEmail(777);user1.setName(231);list.add(user1); // INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) // 1767385817043038210(Long), 123(String), 18(Integer), 666(String) // 1767385817126924289(Long), 231(String), 23(Integer), 777(String)userService.saveBatch(list);} // 保存或修改如果user的id有值则修改没有则保存Testpublic void test_saveOrUpdate(){ // 添加 // INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) // 1767386132609855489(Long), 9999(String), 998(Integer), 999(String)User usernew User();user.setAge(998);user.setEmail(999);user.setName(9999);userService.saveOrUpdate(user); // 修改 // SELECT id,name,age,email FROM user WHERE id? // 1, 111, 99, test1baomidou.com // UPDATE user SET name?, age?, email? WHERE id? // 1999(String), 1999(Integer), 1999(String), 1(Long)User user1new User();user1.setId(1L);user1.setAge(1999);user1.setEmail(1999);user1.setName(1999);userService.saveOrUpdate(user1);}// 修改 // UPDATE user SET name?, age?, email? WHERE id? // 8888(String), 8888(Integer), 8888(String), 1(Long)Testpublic void test_update(){User usernew User();user.setId(1L);user.setAge(8888);user.setEmail(8888);user.setName(8888);userService.updateById(user);} // 移除 // DELETE FROM user WHERE id? // 1767386132609855489(Long)Testpublic void test_remove(){userService.removeById(1767386132609855489L);} // 查询Testpublic void test_getOrList(){ // SELECT id,name,age,email FROM user WHERE id? // 1(Long) // user User(id1, name8888, age8888, email8888)User user userService.getById(1L);System.out.println(user user); // SELECT id,name,age,email FROM user // list [User(id1, name8888, age8888, email8888), User(id3, name111, age28, emailtest3baomidou.com), User(id4, name111, age21, emailtest4baomidou.com), // User(id5, name111, age24, emailtest5baomidou.com), User(id1767361818149871618, name111, age88, email11), User(id1767385817043038210, name123, age18, email666), // User(id1767385817126924289, name231, age23, email777), User(id1767386445735616513, name9999, age998, email999), User(id1767386600643825666, name9999, age998, email999)]ListUser list userService.list(null);System.out.println(list list);} } 分页查询实现 在mapper层增强和service层增强中都提供了分页查询方法。 MyBatis和Mybatis-Plus分页查询 MyBatis1、设置分页参数PageHelper 2、编写sql语句 3、结果封装PageInfo 4、获取分页数据 原理后置拦截器sql语句不要分号结尾因为分页查询底层就是在sql语句后拼接字符串limit x,y。 Mybatis-Plus在MyBatis-Plus中一个插件集合  MybatisPlusInterceptor 只需要把分页插件放到集合中进行了。 Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();//注意DbType.MYSQL导包别导错interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;} 使用分页查询 Testpublic void test_page(){//设置分页参数PageUser page new Page(1,5);//查询后数据会写入原来的page可以使用它获取数据userService.page(page,null);//获取数据ListUser list page.getRecords();//打印数据list.forEach(System.out::println);System.out.println( 获取当前页 page.getCurrent());System.out.println( 每页显示的条数 page.getSize());System.out.println( 总数据数 page.getTotal());System.out.println( 总页数 page.getPages());System.out.println( 是否有上一页 page.hasPrevious());System.out.println( 是否有下一页 page.hasNext());} // SELECT COUNT(*) AS total FROM user // SELECT id,name,age,email FROM user LIMIT ? // 5(Long) // User(id1, name8888, age8888, email8888) // User(id3, name111, age28, emailtest3baomidou.com) // User(id4, name111, age21, emailtest4baomidou.com) // User(id5, name111, age24, emailtest5baomidou.com) // User(id1767361818149871618, name111, age88, email11) // 获取当前页 1 // 每页显示的条数 5 // 总数据数 9 // 总页数 2 // 是否有上一页 false // 是否有下一页 true 自定义的mapper方法使用分页 方法UserMapper接口 public interface UserMapper extends BaseMapperUser { // 参数列表携带IPage接口 // 返回结果为IPageIPage queryPageByAge(IPageUser page, Param(age) Integer Age); } 实现MapperXml ?xml version1.0 encodingUTF-8? !DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.qiu.mapper.UserMapper!-- 记得起别名sql后面不要加分号--select idqueryPageByAge resultTypeuserselect * from user where age #{age}/select /mapper 测试方法 Testpublic void test_page_age(){Page page new PageUser(1,3);userMapper.queryPageByAge(page,22);List records page.getRecords();records.forEach(System.out::println);}结果 条件构造器使用 1、条件构造器作用 Mybatis-Plus的条件构造器可以让我们构建灵活、高效的查询条件。 场景删除 nameJohnage ! 30email like %gmail.com Testpublic void test2(){QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.eq(name,John);queryWrapper.ne(age,30);queryWrapper.like(email,gmail.com); // 上面操作等于delete from user where name John and age !30 and email like %gmail.com% // int delete(Param(ew) WrapperT queryWrapper);userMapper.delete(queryWrapper);} 2、条件构造器继承结构 Wrapper抽象类顶端父类 一般操作UpdateWrapper、QueryWrapper、LambdaUpdateWrapper和LambdaQueryWrapper推荐使用后两个。 UpdateWrapper和LambdaUpdateWrapper一般修改时使用 QueryWrapper和LambdaQueryWrapper一般删除和查询时使用 3、基于QueryWrapper组装条件 SpringBootTest public class WrapperTest {Autowiredprivate UserMapper userMapper;Test//组装查询条件public void test1(){//查询用户名包含a年龄在20到30之间并且邮箱不为null的用户信息//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)QueryWrapperUser queryWrappernew QueryWrapper();queryWrapper.like(name,a).between(age,20,30).isNotNull(email);ListUser list userMapper.selectList(queryWrapper);}Test // 组装排序条件public void test2(){//按年龄降序查询用户如果年龄相同则按id升序排列//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted0 ORDER BY age DESC,id ASCQueryWrapperUser queryWrappernew QueryWrapper();queryWrapper.orderByDesc(age).orderByAsc(id);ListUser users userMapper.selectList(queryWrapper);}Test // 组装删除条件public void test3(){//删除email为空的用户//DELETE FROM t_user WHERE (email IS NULL)QueryWrapperUser queryWrappernew QueryWrapper();queryWrapper.isNull(email);int result userMapper.delete(queryWrapper);}Test // and和or关键字使用(修改)public void test4(){//将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改 // 优先级notandor//UPDATE t_user SET age?, email? WHERE username LIKE ? AND age ? OR email IS NULLQueryWrapperUser queryWrappernew QueryWrapper();queryWrapper.gt(age,20).like(name,a).or().isNull(email);User user new User();user.setAge(18);user.setEmail(useratguigu.com);int result userMapper.update(user, queryWrapper);}Test // 指定列映射查询返回指定的列数据public void test5(){//查询用户信息的username和age字段//SELECT username,age FROM t_userQueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.select(name, age);//selectMaps()返回Map集合列表通常配合select()使用避免User对象中没有被查询到的列值为nullListMapString, Object maps userMapper.selectMaps(queryWrapper);maps.forEach(System.out::println);}Test // condition判断组织条件public void test6(){String name John;int age 18;QueryWrapperUser queryWrapper new QueryWrapper();//判断条件拼接//当name不为null拼接等于, age 1 拼接等于判断//方案1: 手动判断 // import org.junit.platform.commons.util.StringUtils;if (StringUtils.isNotBlank(name)){queryWrapper.eq(name,name);}if (age 1){queryWrapper.eq(age,age);}//方案2: 拼接condition判断//每个条件拼接方法都condition参数,这是一个比较运算,为true追加当前条件!//eq(condition,列名,值)queryWrapper.eq(StringUtils.isNotBlank(name),name,name).eq(age1,age,age);} } 4、基于UpdateWrapper组装条件 Testpublic void test(){ // 如果使用QueryWrapper进行修改需要准备要修改的实体类而且数据不能改为null值。QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.gt(age,18);User user new User();user.setAge(99);user.setName(null);//此时不会修改nameuserMapper.update(user,queryWrapper);// 使用UpdateWrapper修改 // 可以直接携带数据 updateWrapper.set(age,12); // 也可以设置为空 updateWrapper.set(email,null);UpdateWrapperUser updateWrapper new UpdateWrapper();updateWrapper.gt(age,35).set(email,null).set(age,19);userMapper.update(null,updateWrapper);} 5、基于LambdaQueryWrapper组装条件 LambdaQueryWrapper对比QueryWrapper QueryWrapper表示字段名时使用字符串queryWrapper.eq(name,qiu); LambdaQueryWrapper表示字段名时使用实体类的属性引用lambdaQueryWrapper.eq(User::getName,qiu); 提高了代码的可读性和可维护性。 Test//组装查询条件public void test1(){//查询用户名包含a年龄在20到30之间并且邮箱不为null的用户信息LambdaQueryWrapperUser lambdaQueryWrappernew LambdaQueryWrapper();lambdaQueryWrapper.like(User::getName,a).between(User::getAge,20,30).isNotNull(User::getEmail);ListUser list userMapper.selectList(lambdaQueryWrapper);} 6、基于LambdaUpdateWrapper组装条件 Testpublic void test2(){LambdaUpdateWrapperUser updateWrapper new LambdaUpdateWrapper();updateWrapper.gt(User::getAge,35).set(User::getEmail,null).set(User::getAge,19);userMapper.update(null,updateWrapper);} 核心注解使用 TableName TableName(value)加到与数据库表对应的pojo类上value对应的数据库的表名可以不加不加默认使用实体类的名字作为表名忽略大小写。 IServiceUserBaseMapperUser等会根据User类对应的表名在数据库中操作相应的表。 一般数据库表会有 “  t_  ”之类的前缀可以在application.yaml中添加 mybatis-plus.global-config.db-config.table-prefix: t_ 来统一配置如果类上有TableName注解则该配置对此类无效。 TableId TableId(value主键名, type主键策略) 使用场景1.主键的列名与属性名不一致驼峰映射后能对应上的不需要使用 2.指定插入数据时如何生成主键,常用枚举类型如下 ASSIGN_ID分配ID在mybati-plus3.3.0以后会使用雪花算法分配idLong类型AUTO数据库ID自增需要mysql数据库表的主键列设置自增长 主键策略也可以统一设置application.yaml中的mybatis-plus.global-config.db-config.id-type: auto TableField 当普通字段与属性不一致时可以使用该注解手动设置。 Data public class User {TableId(id)private Long userId;TableField(name)private String userName;private Integer age;private String email;TableField(exist false)private String py; } pojo类属性应该与数据库表的字段一一对应属性缺少不报错但不会返回该字段属性比字段多会报错要么删除要么该属性上使用TableField(existfalse)。 MyBatis-Plus高级拓展 逻辑删除实现 逻辑删除是指在表中添加一个字段模拟删除在删除操作时使用假删除方便之后进行数据分析和恢复。 在数据库表中添加删除字段  alter table user add deleted int default 0 ; int类型1为逻辑删除0为未逻辑删除。 在pojo类中添加逻辑删除属性并在属性上添加TableLogic注解 使用该注解后默认执行mybatis-plus提供的删除方法时会自动换成修改方法如果要删除的数据中逻辑删除字段为0就将该字段改为1不为0则不修改。 逻辑删除全局配置 在application.yaml中设置mybatis-plus.global-config.db-config.logic-delete-field: deleted 设置所有逻辑这段的实体字段名为deleted。mybatis-plus.global-config.db-config.logic-delete-value: 1 设置逻辑删除值为1mybatis-plus.global-config.db-config.logic-not-delete-value: 0 设置未逻辑删除值为0 乐观锁实现 场景 可能为500也可能为0。 两个动作都是先取值在减值如果两个动作同时取到1000减值后为500。 资源争抢的解决方法 乐观锁和悲观锁是在并发编程中用于处理并发访问和资源竞争的两种不同的锁机制!! 悲观锁获取资源时把资源上锁确保在减值操作前只有自己获得资源但效率低。 乐观锁获取资源前检查是否资源已被使用没有就操作资源有则等待一段时间后继续尝试获取资源。效率较高但是在并发冲突较为频繁的情况下乐观锁会导致较多的冲突处理和重试操作。 理解点: 悲观锁和乐观锁是两种解决并发数据问题的思路,不是具体技术!!! 具体技术和方案 1.乐观锁实现方案和技术 版本号/时间戳为数据添加一个版本号或时间戳字段每次更新数据时比较当前版本号或时间戳与期望值是否一致一致则更新成功否则表示数据已被修改需要冲突处理。CASCompare-and-Swap使用原子操作比较当前值与旧值是否一致若一致则进行更新操作否则重新尝试。无锁数据结构采用无锁数据结构如无锁队列无锁哈希表等通过使用原子操作实现并发安全。 2.悲观锁实现方案和技术 锁机制使用传统的锁机制如互斥锁或读写锁来保证对共享资源的独占访问。数据库锁在数据库层面使用行级锁或表级锁来控制并发访问。信号量使用信号量来限制对资源的并发访问。 版本号乐观锁的实现流程 1.数据库表添加一个字段version 2.取出数据时获取当前version 3.更新时检查获取版本号是不是数据库当前最新版本号 4.如果是说明没人修改数据执行更新操作set 数据更新version version 1 5.如果不是说明数据被修改了当前数据为无效数据更新失败。 使用mybatis-plus数据使用乐观锁 1. 添加版本号更新插件 Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 版本号更新插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;} 2.乐观锁字段添加Version注解 数据库添加乐观锁字段 ALTER TABLE t_user ADD VERSION INT DEFAULT 1 ; # int 类型 乐观锁字段 表结构 ------------------------------------------------- | Field | Type | Null | Key | Default | Extra | ------------------------------------------------- | id | bigint | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | | age | int | YES | | NULL | | | email | varchar(20) | YES | | NULL | | | deleted | int | YES | | 0 | | | VERSION | int | YES | | 1 | | ------------------------------------------------- 乐观锁字段支持的数据类型只有intIntegerlongLongDateTimestampLocalDateTime 仅支持updateById(id)与update(entry, wrapper)方法 Data public class User {TableId(id)private Long userId;TableField(name)private String userName;private Integer age;private String email; // TableLogic逻辑删除字段 int mybatis-plus下默认逻辑删除为1未逻辑删除为0private Integer deleted;Versionprivate Integer version; } 测试 //演示乐观锁生效场景 Test public void testQuick7(){//步骤1: 先查询,在更新 获取version数据//同时查询两条,但是version唯一,最后更新的失败User user userMapper.selectById(4);User user1 userMapper.selectById(4);user.setAge(20);user1.setAge(30);userMapper.updateById(user);//乐观锁生效,失败!userMapper.updateById(user1); } 结果 ------------------------------------------------------------------------- | id | name | age | email | deleted | VERSION | ------------------------------------------------------------------------- | 1 | Jone | 18 | test1baomidou.com | 0 | 1 | | 2 | Jack | 20 | test2baomidou.com | 0 | 1 | | 3 | Tom | 28 | test3baomidou.com | 0 | 1 | | 4 | Sandy | 20 | test4baomidou.com | 0 | 2 | | 5 | Billie | 24 | test5baomidou.com | 1 | 1 | | 1767361818149871618 | 111 | 88 | 11 | 0 | 1 | | 1767385817043038210 | 123 | 18 | 666 | 0 | 1 | | 1767385817126924289 | 231 | 23 | 777 | 0 | 1 | | 1767386445735616513 | 9999 | 998 | 999 | 0 | 1 | | 1767386600643825666 | 9999 | 998 | 999 | 0 | 1 | ------------------------------------------------------------------------- 防全表更新和删除实现 添加防止全表更新或删除插件 Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 版本号更新插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 防止全表更新或删除interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;} 测试 Testpublic void test(){ // 全表删除userMapper.delete(null);} 结果报错 MyBatis-Plus代码生成器MyBatisX 插件 MyBatisX插件逆向工程 MyBatisX快速代码生成 使用mybatisX插件,自动生成sql语句实现 MybatisX快速开发插件 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/ba5b24/?spmwolai.workspace.0.0.330e767bDepZBf#%E5%8A%9F%E8%83%BD
http://www.pierceye.com/news/564352/

相关文章:

  • 如何用手机做钓鱼网站贵阳建设厅网站
  • 网站建设工作自查报告网站建设的心得体会
  • 网站开发项目设计文档产品seo基础优化
  • 建筑工程招聘网站哪个好wordpress ssr
  • 制作一个网站平台做php网站需要什么软件开发
  • 长沙seo网站管理淮北论坛招聘最新消息兼职
  • .net网站源码下载珠海网站建设珠海
  • 网站被降权严重吗企业营销型网站的内容
  • 网站抓取qq号码原理社交电商平台排行榜
  • 贵阳做网站哪家公司好dw如何在网站做弹窗
  • 怎样做网站底部导航网站建设软件sh
  • 小白学网站建设与设计书如何制作app软件下载
  • 个人网站模板源码一般vs做的网站的总体框架
  • 服务器做网站流程wordpress分站
  • 电子商务平台网站建造莒南做网站
  • 网站文章好几天不收录注册送38元的游戏网站
  • 手机营销型网站建设定制一款软件需要多少钱
  • 网站备案增加域名解析电子信息工程移动互联网 学什么
  • 怎么在网站视频做字幕河北唐山建设工程协会网站
  • 自己做网站导航页腾讯云服务器可以做传奇网站吗
  • 郑州%公司 网站建设页面设计教案
  • 昌邑建设局网站北京seo优化wyhseo
  • 网站访客抓取新媒体营销课程心得体会
  • 网站建设售前域名注册
  • 运动器材网站开发方案失信被执行人名单查询系统
  • 深圳商业网站建设模板网站建设worldpress
  • 宁波网站排名网站开发 哪家好
  • 做网站的软件工程师网站积分程序怎么建设
  • ps网站轮播图怎么做动漫制作专业的来源
  • 怎么知道一个网站是谁做的建筑认证