范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

化繁为简,MyBatisPlus里面的增删改查

  一. MP 里面的增删改查
  在当前盛行的 SpringBoot 项目中,整合持久层这一块,目前主流的有两种:JPA 和 MyBatis-Plus。至于哪个用得更多一些,这个主要还是看每个公司的技术架构,但硬是要说一个最为常用的,我认为是 MyBatis-Plus,而在这里也是对 MyBatis-Plus 的一个使用进行演示
  好了,废话不多说,直接开始吧。为了减少冗余,下面所有 MyBatis-Plus 都使用 MP 来代替 1.1 项目搭建
  项目的创建就直接跳过了,直接从依赖开始吧。开始之前得先弄个表,表怎么弄都行,下面这个是我测试建的,可以参考一下 DROP TABLE IF EXISTS `user`; CREATE TABLE `user`  (   `id` int(0) NOT NULL AUTO_INCREMENT COMMENT "id",   `name` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT "用户名",   `age` int(0) NOT NULL COMMENT "年龄",   `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT "手机号",   `email` varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT "邮箱",   `create_time` datetime(0) NULL DEFAULT NULL COMMENT "创建时间",   `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT "创建人",   `update_time` datetime(0) NULL DEFAULT NULL COMMENT "更改时间",   `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT "更改人",   `is_delete` int(0) NULL DEFAULT NULL COMMENT "是否删除 0-未删除 1-已删除",   PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3554031 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = "用户表" ROW_FORMAT = Dynamic;依赖 (1) 目前 MP 的最新版本                                 com.baomidou                 mybatis-plus-boot-starter                 3.5.2             
  (2) 当然,如果你想使用 MP 中的快速生成实体类,需要添加 MP 中的一个工具依赖且需导入一个模板引擎的依赖 (模板可以自定义,具体看 MP 官网的例子,这里直接使用 Freemark)                                        com.baomidou                 mybatis-plus-generator                 3.5.2                                           org.freemarker                 freemarker                 2.3.31             (3) 以上的都是 MP 中所需的依赖,除此之外,当然还少不了 SpringWeb 的依赖了;我们还需要对数据库进行操作,MySQL 的依赖也必不可缺                 org.springframework.boot                 spring-boot-starter-web                                            mysql                 mysql-connector-java                 runtime             
  2.逆向工程创建实体类
  (1) 其实这个有好几种方法,自己手动创建也行;使用 IDEA 中的一些插件也行;或者使用 MP 官网提供的代码生成模板也行。不管用哪种方法,最终要做的都是一样的,就是把项目搭起来,实体类弄起来。
  (2) 在这里,就直接使用 MP 官网提供的代码模板吧。直接在 MP官网 —— 指南 —— 代码生成器 (新) 就能找到
  (3) copy 这段代码到 maven 工程自带的单元测试中,然后根据注释去修改一下,直接运行即可。  (4) 稍微解释一下怎么使用这个,其实很简单:  *   `url` 、`username` 、`password` :即你数据库连接的地址、用户名、密码 *   `outputDir` :这个就是注释的意思,输出目录嘛~但注意一下,这个写到 java 目录即可。(可参考:"D:code	est	est-demo	s-mybatissrcmainjava") *   `parent` :父包名 (一般是 com.xxx) *   `moduleName` :父包名下的模块名 (即 com.xxx.yyy 这个 yyy 即是这个模块名了) *   `pathInfo` :后面的那个地址即是 mapperxml 的路径了 (可参考:"D:code	est	est-demo	s-mybatissrcmainresourcesmapper") *   `addInclude` :这个就更简单了,你要它帮你生成什么实体类,你就把表名往这这里填,注意的是,名字可别写错,不然识别不出来 *   `addTablePrefix` :这个就是一些表的前缀在生成到 Java 代码中的类名时,给你去掉前缀,没有可以不管他        /**         * mp 逆向工程生成实体类         */        @Test        void contextLoads() {            FastAutoGenerator.create("jdbc:mysql://localhost:3306/ts_mybatis_db?useUnicode=true&characterEncoding=utf8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai", "root", "root")                    .globalConfig(builder -> {                        builder.author("Peng") // 设置作者                                .enableSwagger() // 开启 swagger 模式                                .fileOverride() // 覆盖已生成文件                                .outputDir("D:codetesttest-demots-mybatissrcmainjava"); // 指定输出目录                    })                    .packageConfig(builder -> {                        builder.parent("com.peng") // 设置父包名                                .moduleName("tsmybatis") // 设置父包模块名                                .pathInfo(Collections.singletonMap(OutputFile.xml, "D:codetesttest-demots-mybatissrcmainresourcesmapper")); // 设置mapperXml生成路径                    })                    .strategyConfig(builder -> {                        builder.addInclude("user") // 设置需要生成的表名                                .addTablePrefix("t_", "c_"); // 设置过滤表前缀                    })                    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板                    .execute();        }
  (5) 注意,这个如果没有加  模板引擎  运行的时候会报错,加上 Freemarker 依赖即可
  3.大功告成之后,在你的项目中 MP 就会把整个项目基础模块都给搭好了,如下图:
  4.注意,mapper 里面的扫描在 MP 中并不会帮你生成,所以这个 MapperScan 还需要自己去加上,在启动类上面加上一个  @MapperScan  这个注解,去扫描你的 mapper 文件 @MapperScan(value = {"com.peng.tsmybatis.mapper"})1.2 极其便利的单表操作
  以下的测试都是,都是使用 Postman 进行测试的,在这里为了方便测试,全都是使用 GetMapping 去调用 1.2.1 增    @Resource     IUserService userService;      @GetMapping("/add")     public boolean add() {         User user = new User();         user.setName("李四");         user.setAge(18);         return userService.save(user);     }
  (1) 很简单,其实就是 new 了一个对象扔到 MP 的方法里面而已,通过观察 IUserService 这个接口可以发现,它继承了  IService  且泛型里面放的就是你对应的实体类 User,因此在此 service 下的一切 MP 相关的方法都是针对 User 这个实体类的操作
  (2) 因为 User 这个实体类是对应数据库中的 User 表的,所以需要注意的是当前的这个表设计中是否有哪些必填的字段,如果遗漏了(即没有 set 那个值到这个 User 对象中),那么就会报错
  (3) 其他就没什么需要注意的,你想添加什么内容,就往这个 User 对象中 set 什么进去就可以了。成功即返回 true 了,反之则 false 了。另外如果你想查看 MP 帮你执行的 SQL 可以在 yaml 或者 properties 中加上以下这段。我这里使用的是 yaml 文件配置 mybatis-plus:   configuration:     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印 mybatis-plus 的执行日志
  添加之后访问接口时便会有以下日志打印:
  (4) 我这里使用的是 Postman 来测试这个接口,返回 true 则表示成功了,此时去数据库查看便可发现,多了一条 name = 李四;age = 18 的记录
  1.2.2 批增
  (1) 当我们有当量添加的需求时,不停的去 new 对象太麻烦了,因此 MP 为我们提供了批量添加的方法。
  (2) 还是很简单,只是由原来的一个对象变成了集合而已。我们只需要把需要添加的信息,收集成一个集合即可,然后把这个集合丢给 MP ,剩下的事情 MP 就会帮我们去做了,像这样:     @GetMapping("/addBatch")     public boolean addBatch() {         List entityList = new ArrayList<>();         for (int i = 1; i <= 10; i++) {             User user = new User();             user.setName("张三" + i);             user.setAge(20 + i);             entityList.add(user);         }         return userService.saveBatch(entityList);     }
  (3) 通过 Postman 访问  http://localhost:8082/addBatch  这个接口后返回 true,表示成功了,此时查看数据库就多了10条数据:
  (4) 玩法很简单,只是从一个对象,变成了一个集合而已。所以 MP 还是很方便的,它在原来的 MyBatis 上增加了很多对数据库的操作方法,这些都只是它最基础的一些操作。 1.2.3 改、批改
  (1) 这个与增其实是一样的,唯一的区别是需要传一个 ID,不然 MP 不知道你需要对哪条记录进行修改。所以只需要在上面的基础上多去 set 一个 id 就可以了,像这样:     @GetMapping("/update")     public boolean update() {         User entity = new User();         entity.setId(1);         entity.setName("灵儿");         entity.setAge(16);         return userService.updateById(entity);     }      @GetMapping("/updateBatch")     public boolean updateBatch() {         List entityList = new ArrayList<>();         for (int i = 1; i <= 10; i++) {             User user = new User();             user.setId(i + 1);             user.setName("拜月" + i);             user.setAge(30 + i);             entityList.add(user);         }         return userService.updateBatchById(entityList);     }
  (2) 增和改其实本质上是差不多的,运行成功之后,查看数据库的结果就变成了这样:
  1.2.4 查
  (1) 在 MP 中,查就更简单了,因为在我们实际项目中用的最多的就是查询了。当然往往我们的查询会伴随着很多条件,在 MP 中给我们提供了条件构造器,也是能够满足到我们不写 SQL 的场景的,这个后续再细聊。
  (2) 对于单表的操作,在 MP 中就一个 list() 的方法就完成了     @GetMapping("/list")     public List list() {         return userService.list();     }
  (3) 通过 Postman 访问接口后,在 IDEA 中可以看到 MP 中打印出来的日志[图片上传失败...(image-186b72-1668753721260)]
  (4) 可能你会说,后面那些字段都没有数据,你不想去查出来,浪费资源,那应该怎么办呢?这时就需要我们使用条件构造器了,通过条件构造器去进行操作     @GetMapping("/list")     public List list() {         QueryWrapper qw = new QueryWrapper<>();         qw.select("id","name","age"); //        qw.lambda().select(User::getId, User::getName, User::getAge);  JDK8的方法         return userService.list(qw);     }
  (5) 注意,括号里面的字符串需要与你数据库上能够对应上,否者查不出来的,很好理解,就和自己写 SQL 一样,如果查询的字段表中没有,显然也是查不出来的,MP 只是帮我们把 SQL 给写了而已 12.5 删、批删
  (1) 这个其实和修改类似的,也是需要传一个 ID ,不然 MP 不知道你要删除的是哪一条数据。
  (2) 还是一样,删除单条记录,只需要 new 一个对象然后传一个你要删除的 ID 进去,MP 就会帮你处理了;而批删的话则是一个集合了,也是需要传 ID 的     @GetMapping("/delete")     public Boolean delete() {         User entity = new User();         entity.setId(1);         return userService.removeById(entity);     }      @GetMapping("/deleteBatch")     public boolean deleteBatch() {         List entityList = new ArrayList<>();         for (int i = 1; i <= 10; i++) {             User user = new User();             user.setId(i + 1);             entityList.add(user);         }         return userService.removeBatchByIds(entityList);     }
  (3) 与修改稍微有点不一样的是,你不需要传修改的值过去了,只需要传你要删除的 ID 即可。
  (4) 需要注意的是,MP 的这个方法是物理删除的。而在我们实际开发中,有些业务场景是逻辑删除的,也就是说我们的表中有一个类似  is_delete  的字段,删除时只需要修改这个字段由 0 变 1或是由 1 变 0 即可,具体看实际需求。
  (5) 在 MP 中同样也封装了逻辑删除的一些配置,当你业务是逻辑删除时,可以在 IDEA 中这样去配置,告诉 MP 我这里使用的是逻辑删除,别真把我的记录给删除掉了~很简单,只需要在逻辑删除的字段上加一个注解就可以搞定     @TableLogic(value = "0",delval = "1")     private Integer isDelete;
  (6) @TableLogic() 就是这个注解,可以去下载 MP 源码查看:第一个参数是未删除的值,第二个参数是已删除的值,这里就不放图片了,感兴趣的朋友可以点进去瞅瞅。
  (7) 除了这种配置方式外,还可以在 application.yaml 或者 application.properties 那些配置文件中进行配置,就是说,当你有好多个实体类,而好多个实体类都是逻辑删除,那么也就意味着每一个注解里面的参数都要写上 value = "0",delval = "1" 这样一段,显然过于冗余。所以我们可以在配置文件中进行一个全局配置,像这样: mybatis-plus:   global-config:     db-config:       logic-delete-field: 1 #删除       logic-not-delete-value: 0 #未删除
  (8) 加了这个之后,MP 就会对你当前的实体类所对应的表的 CRUD 操作都是带上逻辑删除的一个逻辑,也就是  is_delete=0  ,就是当前记录是未删除的。
  (9) 如果在前面开启了 MP 的执行日志就会发现,MP 在执行 CRUD 的时候,最后都加上了一个  WHERE is_delete=0  的一个判断 1.3 一些小扩展
  (1) 一般而言,我们设计表的时候,有一些字段是往往都是亘古不变的,像类似 create_time、update_time 那些,像我们当前的这个表:
  (2) 像刚刚提到的两个字段,在我们每一次添加或者修改的时候都需要去更新一下时间,一个两个还好,如果多起来的话就会发现好多代码都是重复的,特别冗余。对此 MP 给我提供了解决方案,可以在进行插入、修改的时候就自动帮我们进行一个处理了
  (3) 也和上面处理逻辑删除一样,一个注解就完事了,但这个需要去配置一下,创建一个配置类,实现  MetaObjectHandler  这个接口,重写他的两个方法就可以了,如下@Component public class MyMetaObjectHandler implements MetaObjectHandler {      @Override     public void insertFill(MetaObject metaObject) {         /*         参数一: 属性的名称         参数二: 你想给这个属性设置的值         参数三: 元对象,所有入参的 MetaObject 必定是 entity 或其子类的 MetaObject          */         this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);         this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);         this.setFieldValByName("isDelete", 0, metaObject);     }      @Override     public void updateFill(MetaObject metaObject) {         this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);     } }
  (4) 写好配置类之后,在实体类上使用 @TableField() 这个注解和这个配置类呼应上就可以了,像这样     @TableField(fill = FieldFill.INSERT)     private LocalDateTime createTime;      @TableField(fill = FieldFill.INSERT_UPDATE)     private LocalDateTime updateTime;      @TableField(fill = FieldFill.INSERT)     private Integer isDelete; 复制代码
  (5) 这里的意思就是说:当进行 INSERT 操作的时候,自动帮我 createTime、updateTime 字段都设置成当前时间,而 isDelete 则默认设置成 0;当 UPDATE 的时候,只更改 updateTime 的时候改成当前更改的时间
  (6) 实践才是检验真理的唯一标准,咱们来试一下。我这里为了省事,就不用 Postman 去发请求访问接口了,直接在单元测试中进行     @Resource     private UserMapper userMapper;      @Test     public void test08() {         User user = new User();         user.setName("伏羲");         user.setAge(131);          int result = userMapper.insert(user);         System.out.println(result == 1 ? "添加成功" : "添加失败");     }
  从控制台打印的日志可以看到,create_time, update_time, is_delete 这三个值 MP 默认帮我去添加了数据,而添加的数据正是我们在配置文件上设置的
  (7) UPDATE 也是一样的,这里就不演示了 1.4 小结在 MP 中对单表的操作是非常方便的,如果对于需要连表的一对多或多对多,需要在对应的实体类上加一些注解啥的,具体还没去研究过;因为个人觉得,在一些较为复杂的表结构中,还不如自己写 SQL 来得快。但是如果是对单表操作,强烈建议用 MP 自带的方法,谁还会写 SQL 呢~ 当然目前为止演示的都是很简单的 CRUD,实际操作上肯定是不一样的。因为在我们的实际操作中,可能会频繁地使用 MP 中的条件构造器去根据业务不同来返回数据。这个会在后面继续深入去演示一些 MP 中常用到的方法就是 另外需要说明一下的是,上述演示的代码中,都是在 Controller层中进行的。我这里是为了方便,MP 中的 IService 中已经有 CRUD 的方法了,就没去到 service 层去操作。按照代码的规范,还是更建议去到 service 层中处理业务逻辑的。 可能第三点会有些绕口,基础好的可能明白我说的意思了,而至于基础稍微没那么好的,既然都看到这里了,我还是在简单的演示一下标准版吧...比如要返回一个"用户菜单" (1) Controller      @Resource         private IUserService userService;          @GetMapping("/userMenus")         public List userMenus() {             List result = userService.userMenus();             //如果结果不为空,返回结果;否之返回 null             return ObjectUtils.isNotEmpty(result) ? result : null;         }
  (2) Service,注入一个 Mapper,其中也有 MP 自带的方法。正常来说,上面演示的都应该在这里,也就是 Service 层进行处理,再返回到 Controller 中@Autowired         private UserMapper userMapper;          @Override         public List userMenus() {             QueryWrapper qw = new QueryWrapper<>();             qw.lambda().select(User::getId, User::getName, User::getAge);             return userMapper.selectList(qw);         }
  (3) 如果需要写 SQL ,那么也是一样的,只是跳到 Mapper 这个接口,然后再跳到 MapperXML 中去写而已,当然你也可以在 Mapper 时使用一些 MyBatis 的注解(@Select、@Update...之类的),我这里直接放个图片了,就不一步步演示了
  或者类似这样

抓机会赢证明渡边雄太救火表现获认可杜兰特放话欲让蔡崇信留人休赛期与猛龙的合同到期之后,渡边雄太在并未获得续约的情况下,则得到了篮网为其抛出的橄榄枝,蔡崇信仅用一份197万的无保障合同,便把他给带到了布鲁克林。渡边雄太本赛季加盟篮网,担任救世界杯再现爆冷场面,黑马并非只靠运气作者西蒙日前,卡塔尔世界杯再现爆冷场面,在日本与德国的对决中,虽然德国队先通过点球得分,但日本队后发制人,连续攻入两球,最终以21战胜德国队。11月23日,日本队守门员权田修一(右墨西哥为何是中北美洲的老大?连续七届打进十六强2022世界杯世界杯里有一个钉子户,无论在欧洲举办,在南美洲举办,在亚洲举办,在非洲举办,都有这支中游球队的身影。甚至更进一步讲,在世界杯十六强里,这支球队也是个钉子户,哪里都有他国乒官宣新任命,秦志戬赴任新岗位,王楚钦新主管教练或将揭晓国乒官宣最新任命,秦志戬赴任新岗位,王楚钦新任主管教练或将揭晓!一起来关注一下国乒的最新消息,在全锦赛和亚洲杯的比赛陆续结束之后,国乒主力迎来了短暂的调整时间,不过留给大家休息的时8年后无冕之王回归,荷兰队本届世界杯能走多远?要说今年最大牌的教练是谁,那肯定是荷兰队的主教练老帅范加尔,在荷兰队公布大名单之后,球队最大的明星竟然是主教练。11月22日,范加尔率领的荷兰队一改昔日全攻全守的酣畅打法,用稳健的被告人吴亦凡强奸聚众淫乱案一审宣判2022年11月25日上午,北京市朝阳区人民法院一审公开宣判被告人吴亦凡强奸聚众淫乱案,对被告人吴亦凡以强奸罪判处有期徒刑十一年六个月,附加驱逐出境以聚众淫乱罪判处有期徒刑一年十个聚众淫乱罪为什么是刑事犯罪?如何界定?律师解读有哪些人们以为是私事的行为其实是违法犯罪行为?聚众淫乱就是其中之一。中华人民共和国刑法第三百零一条规定,聚众进行淫乱活动的,对首要分子或者多次参加的,处五年以下有期徒刑拘役或者管制吴亦凡获刑13年,回顾他的半生,从顶流到阶下囚,被欲望猛烈反噬吴亦凡事件一审判决结果终于出来了!根据北京朝阳法院消息,吴亦凡因强奸罪聚众淫乱罪,数罪并罚,附加驱逐出境,被判13年!也就是说,吴亦凡要在服刑完之后,还将被驱逐出境回到加拿大。可以2023德国大师赛资格赛中国球员已有7人晋级正赛占比高达392023德国大师赛资格赛,张安达52胜詹姆斯卡希尔肖国栋54胜侯赛因瓦菲晋级正赛。截止25日凌晨,32强已产生18名,中国7人(赵心童田鹏飞赵剑波彭弈淞颜丙涛张安达肖国栋),占比高世界杯悲喜一夜!日本爆大冷,西班牙70狂胜,德国或提前出局2022年卡塔尔足球世界杯进行了E组合F组首轮比赛,又迎来疯狂比赛日,日本队2比1逆转德国,爆出大冷门,西班牙7比0狂胜哥斯达黎加也是比较少见的现象。克罗地亚被摩洛哥0比0逼平,比你也来踢世界杯了?本届世界杯球员与NBA球员撞脸撞名大合集昨日世界杯喀麦隆与瑞士的比赛中,喀麦隆的20号后卫姆贝莫因长相被刷屏,只因他长得太像篮球界的超级巨星勒布朗詹姆斯,尤其是侧脸简直像得离谱。不多说,直接上图在姆贝莫的球员评分处,球迷
人生之悲哀!四川老人攒一辈子的钱,一次生病全没了人活在这个世界上就必定离不开一个字,那么就是钱。有人说钱不是万能的,但是在这一个残酷的社会上没有钱却是万万不能的。我们有的时候会大谈理想,大谈自己的远大目标而视金钱为粪土,觉得谈钱汪峰大女儿的亲生母亲,现实中真的比章子怡还美吗?葛荟婕17岁的时候已经是小有成就的模特儿,她有着1米77的身高,前凸后翘的身材,加上一张充满高级感和风情感的脸孔,外型称得上很有优势。但葛荟婕没有在模特行业得到更大的发展,因为她未岁月不饶人!我们要做好告别梅西的准备了加盟巴黎圣日耳曼7月有余,梅西还是没能找回状态代表大巴黎出战7场欧冠比赛,打进5球没有助攻。截至202122赛季法甲第28轮,代表球队出战18场联赛比赛,打进2球送出10记助攻。梅英媒西方金融霸权走向末路资料图英国经济学人近日发表文章称,西方各国对俄罗斯发动大规模的经济制裁行动,意味着一个高风险经济战争时代的到来,世界经济进一步分裂。文章指出,西方世界对俄罗斯采取的制裁措施,造成俄埃及金字塔为什么不让攀爬?一外国游客爬上去后才知道禁爬的原因我国是一个有着上下五千年历史的文明古国,历史文化遗产数不胜数,以至于到了现在还对我们产生着非常深厚的影响。还有一些古建筑,例如长城故宫之类的更是令国内外的人都为之惊叹,成为了我国的朝鲜观察,朝鲜导游为什么不劝游客购物?在国内跟团旅游时,大家都有这样的体验,就是导游经常会引导游客进商店购物。而且景区内的商品卖得很贵,游客不购物,或是购物比较少,导游的脸色会很难看。新闻上甚至出现过导游骂游客的情况。2022年(3月最新)vivoiQOO10006000元高性价手机挑选指南这里是太平洋知科技,如果本文对你有帮助,欢迎点赞关注我。往期精彩回顾2022年(3月最新)手机全攻略10005000各价位高性价手机推荐上期我们说到了10005000元全品牌的手机刘诗诗终于不再人淡如菊!最新代言大片造型封神,穿皮衣A炸刘诗诗虽然一直以来在大家心目中的形象都是人淡如菊的感觉,但是对于一些很帅气的造型,刘诗诗演绎起来也十分的得心应手,就拿她最近的一次大片造型来说,这次刘诗诗的整体风格会更偏帅气感一些跌价超10000元!鸿蒙系统512GB,华为奢侈二手机降至低端市场?如果要调查的数码爱好者与消费者,选择数码产品的首要标准是什么?肯定有很多人都会回答出手机的性能配置与价格。一部手机的配置决定了手机的使用上限,而价格又限制了消费人群,可以说是十分重12GB256GB骁龙888Plus,现已跌至2199元,一亿像素旗舰一降再降正常情况下,一个商品的利润越低,那么它就越难降价,但是在手机行业中却已经完全相反了,利润低的高性价比手机,售价变动速度非常快,至于不以性价比为卖点的手机,价格反而更稳定,之前在手机今日油价2022年3月19日最新9295汽油,柴油价格,油价刚大涨今天的油价在前天晚上刚大涨0。59元升0。71元升,下次油价调整将在3月31日晚进行,目前刚经过一个工作日的统计,原油变化率6。68,预计下调油价290元吨(0。22元升0。26元