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

合肥网站代运营公司有哪些福建省建设质量安全协会网站

合肥网站代运营公司有哪些,福建省建设质量安全协会网站,怎样加盟网站建设,seo推广知识文章目录 前言一、条件构造器1.1 什么是条件构造器1.2 QueryWrapper1.3 UpdateWrapper1.4 LambdaWrapper 二、自定义 SQL 语句2.1 自定义 SQL 的基本用法2.2 自定义 SQL 实现多表查询 三、Service 接口3.1 对 Service 接口的认识3.2 实现 Service 接口3.3 实现增删改查功能3.4 … 文章目录 前言一、条件构造器1.1 什么是条件构造器1.2 QueryWrapper1.3 UpdateWrapper1.4 LambdaWrapper 二、自定义 SQL 语句2.1 自定义 SQL 的基本用法2.2 自定义 SQL 实现多表查询 三、Service 接口3.1 对 Service 接口的认识3.2 实现 Service 接口3.3 实现增删改查功能3.4 Lambda 功能 前言 在前文中介绍了 MyBatis Plus 的一些基础功能我们发现使用MyBatis Plus 可以非常简单的就实现对单表的增删改查操作。但是这些操作对应的 SQL 语句都非常简单如果是面对一些复杂的 SQL 或者多表查询这样的情况就需要我们自己来重新组织 SQL 语句了。 本文将重点探索 MyBatis Plus 的条件构造器、自定义SQL语句来解决这些复杂情况然后实现 MyBatis Plus 提供的通用的 Service 接口以展示如何在项目中使用 MyBatis Plus。 一、条件构造器 1.1 什么是条件构造器 在数据库中除了新增操作之外修改、删除、查询的 SQL 语句中都需要指定 where 条件。在 BaseMapper中提供的相关的方法除了提供以 id 作为 where 的条件之外也都支持更加复杂的 where 条件。 我们可以看到在上面的BaseMapper这些方法中有很多方法都有一个 Wrapper 参数而这个 Wrapper 就是条件构造器的抽象类这个类有许多的实现类 这些类就是条件构造器它是 MyBatis Plus 中的一种查询条件封装方式用于构建SQL语句中的WHERE条件部分。这些构造器的主要作用是根据给定的条件构建数据库操作的条件语句以实现查询、更新、删除等操作。 其中Wrapper 的子类 AbstractWrapper 提供了where中包含的所有条件构造方法 而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法允许指定查询字段 而UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法允许指定SQL中的SET部分 另外我们还发现有一组与Lambda相关的条件构造器为什么会存在这组构造器将在下文进行说明。 下面让我来演示一下其中一些构造器主要的用法。 1.2 QueryWrapper QueryWrapper 顾名思义就是用于构建查询条件的WHERE子句的条件构造器。它提供了多种方法来构建条件包括等值条件、范围条件、模糊查询等。 示例一现在要求查询出user表中名字带 o并且存款不少于 1000 的用户 Test void testQueryMapper() {// 1. 构造查询条件 where name like %o% and balance 1000QueryWrapperUser wrapper new QueryWrapperUser().select(id, username, info, balance).like(username, o).ge(balance, 1000);// 2. 根据 where 条件进行查询ListUser users userMapper.selectList(wrapper);users.forEach(System.out::println); }以下是对上述代码示例的说明 在此代码中我们首先创建了一个QueryWrapperUser对象用于构建查询条件的WHERE子句。然后通过链式方法调用来定义查询条件 .select(id, username, info, balance)指定了要选择的列包括id、username、info和balance。 .like(username, o)设置了查询条件要查找用户名中包含字母’o’的记录类似于SQL中的 WHERE username LIKE %o%。 .ge(balance, 1000)设置了查询条件筛选出余额大于或等于1000的记录。 接下来使用userMapper执行查询操作通过调用selectList(wrapper)方法执行带有指定条件的SQL查询。 运行结果 查询的结果被存储在一个ListUser对象中然后通过users.forEach(System.out::println)遍历列表将每个用户的详细信息打印到控制台。执行代码后运行结果如下所示 上述示例演示了如何使用QueryWrapper构建查询条件以检索数据库表中符合特定条件的记录。这对于执行复杂的查询操作非常有用。 另外QueryWrapper 也可以用于 Update 操作。 示例二使用 QueryWrapper 进行 update 操作更新用户名为Jack的用户的余额为 1000 Test void testUpdateByQueryWrapper() {// 1. 构造查询条件where name JackQueryWrapperUser wrapper new QueryWrapperUser().eq(username, Jack);// 2. 准备更新数据user 对象中的非空数据会作为 SET 的内容User user new User();user.setBalance(1000);// 3. 更新userMapper.update(user, wrapper); }对上述代码的说明 首先构建了一个QueryWrapperUser对象用于构建查询条件。在这个例子中使用了.eq(username, Jack)来设置查询条件即要查找用户名为Jack的记录。这相当于SQL中的 WHERE username Jack。 接下来准备要更新的数据。创建一个User对象并设置了要更新的字段其中user.setBalance(1000)将余额设置为1000。在user对象中非空数据会作为UPDATE语句的SET部分内容。 最后使用userMapper.update(user, wrapper)来执行更新操作。这将更新满足QueryWrapper条件的记录将username为Jack的用户的余额更新为1000。 运行结果 执行代码后运行结果如下所示 上述示例演示了如何使用QueryWrapper构建查询条件并执行更新操作将指定条件的记录进行更新。这是一个示例演示了使用QueryWrapper来进行数据库更新操作。 1.3 UpdateWrapper UpdateWrapper是用于构建更新操作的WHERE条件构造器。它允许设置更新的字段和更新的条件。以下是一些UpdateWrapper的主要用法示例 示例更新id为 1, 2, 4 的用户的余额每个人的余额都扣 200 Test void testUpdateQuery() {// 1. 准备查询条件where id in (1, 2, 4)UpdateWrapperUser wrapper new UpdateWrapperUser().setSql(balance balance - 200).in(id, Arrays.asList(1, 2, 4));// 2. 更新注意此时 update 的第一个参数为 nulluserMapper.update(null, wrapper); }对上述代码的说明 首先创建了一个UpdateWrapperUser对象用于构建更新操作的WHERE条件。在这个例子中我们使用.in(id, Arrays.asList(1, 2, 4))来设置查询条件即要更新id在1、2、4范围内的记录。这相当于SQL中的 WHERE id IN (1, 2, 4)。 接下来使用.setSql(balance balance - 200)来设置更新操作的内容。这表示要将balance字段减少200。这相当于SQL中的 SET balance balance - 200。 最后使用userMapper.update(null, wrapper)来执行更新操作。需要注意的是在这里update方法的第一个参数为null因为在UpdateWrapper中已经设置了更新的条件和内容。 执行代码后运行结果如下所示 上述示例演示了如何使用UpdateWrapper构建更新操作的WHERE条件并执行更新操作以减少满足条件的记录的余额。这是一个示例演示了使用UpdateWrapper进行数据库更新操作。 1.4 LambdaWrapper 通过上面的几个示例可以发现无论是QueryWrapper还是UpdateWrapper在构造条件的时候都出现了硬编码导致使用了字符串魔法值。这在编程规范中显然是不推荐的。那怎么样才能不写字段名又能知道字段名呢 其中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给条件构造器就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。因此Mybatis Plus又提供了一套基于 Lambda的Wrapper包含两个类 LambdaQueryWrapperLambdaUpdateWrapper 分别对应QueryWrapper和UpdateWrapper。、 下面以 LambdaQueryWrapper 为例演示如何使用Lambda条件构造器进行上文的查询操作。 Testvoid testLambdaQueryMapper() {// 1. 准备查询条件where name like %o% and balance 1000LambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser().select(User::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, o).ge(User::getBalance, 1000);// 2. 查询ListUser users userMapper.selectList(wrapper);users.forEach(System.out::println);} 对上述代码的说明 创建了一个LambdaQueryWrapperUser对象用于构建查询条件。在这个例子中使用了Lambda表达式通过User::getXXX方式来引用实体类User的字段而不需要写字段名的字符串。这大大提高了代码的可读性和可维护性。 设置了查询条件使用like方法进行模糊查询匹配username字段中包含字母o的记录使用ge方法筛选balance字段大于或等于1000的记录。同时通过select方法指定了查询结果中的字段。 最后使用userMapper.selectList(wrapper)执行查询操作将满足条件的记录存储在users列表中并使用forEach遍历并打印每个用户的详细信息。 运行代码后运行结果如下所示 这个示例演示了如何使用LambdaQueryWrapper构建查询条件不需要硬编码字段名而是使用Lambda表达式引用实体类的字段提高了代码的可读性和可维护性。 二、自定义 SQL 语句 在上面的演示 UpdateWrapper 的例子中直接在代码中编写了更新的 SQL 语句 这种写法在实际开发中一般都是不允许的因为 SQL 语句最好都维护在持久层而不是业务层。就从这个案例来说由于条件是in语句只能将SQL写在Mapper.xml文件利用foreach来生成动态SQL。这实在是太麻烦了假如查询条件更复杂动态SQL的编写也会更加复杂。 所以Mybatis Plus 提供了自定义 SQL 功能可以让我们利用 Wrapper 生成查询条件再结合Mapper.xml 编写 SQL 语句。 2.1 自定义 SQL 的基本用法 对于上面的例子我们可以改写成自定义 SQL 的形式。 首先在UserMapper 接口中新增一个方法updateBalanceByIds public interface UserMapper extends BaseMapperUser {void updateBalanceByIds(Param(ew) QueryWrapperUser wrapper, Param(money) int money); }然后在 UserMapper.xml 中编写该方法对应的 SQL 语句 update idupdateBalanceByIdsUPDATE user SET balance balance - ${money} ${ew.customSqlSegment} /update注意最后使用${ew.customSqlSegment}拼接由 Wrapper 构造的查询条件。 然后创建一个单元测试方法testCustomSQLForUpdate来测试我们的自定义SQL是否生效 Test void testCustomSQLForUpdate() {// 1. 要扣减的金额int amount 200;// 2. 准备查询条件QueryWrapperUser wrapper new QueryWrapperUser().in(id, Arrays.asList(1, 2, 4));// 3. 执行更新userMapper.updateBalanceByIds(wrapper, amount); }运行结果 2.2 自定义 SQL 实现多表查询 MyBatis Plus 本身不支持多表查询但我们可以使用 Wrapper 来自定义多表查询的条件以达到多表查询的效果。例如现在有一个地址表其结构如下 通过用户id与之关联现在要查询出地址在北京并且用户id在 124 之间的用户如果使用 MyBatis要编写的SQL语句如下 select idqueryUserByIdAndAddr resultTypecom.demo.mp.domain.po.UserSELECT *FROM user uINNER JOIN address a ON u.id a.user_idWHERE u.idforeach collectionids separator, itemid openIN ( close)#{id}/foreachAND a.city #{city}/select可以看出其中最复杂的就是WHERE条件的编写如果业务复杂一些这里的SQL会更加复杂。但是基于自定义 SQL 结合 Wrapper 的写法我们就可以利用 Wrapper 来构建查询条件然后手写SELECT及FROM部分实现多表查询。 首先查询条件可以像下面这样 Test void testCustomJoinAddress() {// 1. 准备查询条件QueryWrapperUser wrapper new QueryWrapperUser().in(u.id, Arrays.asList(1, 2, 4)).eq(a.city, 北京);// 2. 调用自定义方法ListUser users userMapper.queryUserByIdAndAddr(wrapper);users.forEach(System.out::println); }其中u代表user表a 代表 address 表。 然后在UserMapper接口中实现queryUserByIdAndAddr方法 Select(SELECT u.* FROM user u INNER JOIN address a ON u.id a.user_id ${ew.customSqlSegment}) ListUser queryUserByIdAndAddr(Param(ew) QueryWrapperUser wrapper);注意此时可以直接将SQL语句以注解的方式写在对应的方法上面。当然也可以在UserMapper.xml中写 SQL select idqueryUserByIdAndAddr resultTypecom.demo.mp.domain.po.UserSELECT * FROM user u INNER JOIN address a ON u.id a.user_id ${ew.customSqlSegment} /select三、Service 接口 3.1 对 Service 接口的认识 Mybatis Plus 不仅提供了 BaseMapper接口还提供了通用的Service层接口及默认实现封装了一些常用的service模板方法。 其中通用接口为IService默认实现为ServiceImpl其中封装的方法可以分为以下几类 save新增remove删除update更新get查询单个结果list查询集合结果count计数page分页查询 首先让我们来看看 IService接口中增删改查相关功能的方法 新增 save是新增单个元素saveBatch是批量新增saveOrUpdate是根据id判断如果数据存在就更新不存在则新增saveOrUpdateBatch是批量的新增或修改 删除 removeById根据id删除removeByIds根据id批量删除removeByMap根据Map中的键值对为条件删除remove(WrapperT)根据Wrapper条件删除 修改 updateById根据id修改update(WrapperT)根据UpdateWrapper修改Wrapper中包含set和where部分update(TWrapperT)按照T内的数据修改与Wrapper匹配到的数据updateBatchById根据id批量修改 Get 相关方法 getById根据id查询1条数据getOne(WrapperT)根据Wrapper查询1条数据getBaseMapper获取Service内的BaseMapper实现某些时候需要直接调用Mapper内的自定义SQL时可以用这个方法获取到Mapper 获取 List 相关方法 listByIds根据id批量查询list(WrapperT)根据Wrapper条件查询多条数据list()查询所有 Count计数相关方法 count()统计所有数量count(WrapperT)统计符合Wrapper条件的数据数量 3.2 实现 Service 接口 由于Service层中经常需要定义与业务有关的自定义方法因此我们不能直接使用IService而是自定义Service接口然后继承IService以拓展方法。同时让自定义的Service实现类继承ServiceImpl这样就不用自己实现IService中的接口了。 首先定义IUserService继承IService接口 public interface IUserService extends IServiceUser { }然后编写UserServiceImpl类继承ServiceImpl类实现UserService接口 Service public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService { }最终Service的目录结构如下 3.3 实现增删改查功能 上面已经实现了Service层的功能接下来我们就能够快速实现下面 4 个接口 编号接口请求方式请求路径请求参数返回值1新增用户POST/users用户表单实体无2删除用户DELETE/users/{id}用户id无3根据id查询用户GET/users/{id}用户id用户 VO4根据id批量查询GET/users用户id集合用户 VO 集合 首先需要为这些接口实现两个实体类 UserFormDTO代表新增时的用户表单UserVO代表查询的返回结果。 首先是UserFormDTO Data ApiModel(description 用户表单实体) public class UserFormDTO {ApiModelProperty(id)private Long id;ApiModelProperty(用户名)private String username;ApiModelProperty(密码)private String password;ApiModelProperty(注册手机号)private String phone;ApiModelProperty(详细信息JSON风格)private String info;ApiModelProperty(账户余额)private Integer balance; }然后是UserVO Data ApiModel(description 用户VO实体) public class UserVO {ApiModelProperty(用户id)private Long id;ApiModelProperty(用户名)private String username;ApiModelProperty(详细信息)private String info;ApiModelProperty(使用状态1正常 2冻结)private Integer status;ApiModelProperty(账户余额)private Integer balance; }最后按照RESTFul风格编写Controller接口方法 Api(tags 用户管理接口) RequestMapping(/user) RestController public class UserController {Autowiredprivate IUserService userService;PostMappingApiOperation(新增用户接口)public void saveUser(RequestBody UserFormDTO userFormDTO){// 1. 将 DTO 转为 POUser user BeanUtil.copyProperties(userFormDTO, User.class);// 2. 保存userService.save(user);}DeleteMapping(/{id})ApiOperation(根据id删除用户接口)public void removeUserById(PathVariable(id) Long id){userService.removeById(id);}GetMapping(/{id})ApiOperation(根据id查询用户接口)public UserVO queryUserById(PathVariable(id) Long id){// 1. 查询 PO 对象User user userService.getById(id);// 2. 将 PO 转换为 VO 并返回return BeanUtil.copyProperties(user, UserVO.class);}GetMappingApiOperation(根据id批量查询用户接口)public ListUserVO queryUserByIds(RequestParam(ids) ListLong ids){// 1. 查询 PO 对象集合ListUser users userService.listByIds(ids);// 2. 将 PO 转换为 VO 并返回return BeanUtil.copyToList(users, UserVO.class);} }可以看到上述接口都直接在 controller 即可实现无需编写任何service代码非常方便。 通过上面的controller类可以发现实现单表简单的增删改查操作非常简单不过一些带有业务逻辑的接口则需要在service中自定义实现了。 例如这个需求 根据id扣减用户余额。 这看起来是个简单修改功能只要修改用户余额即可。但这个业务包含一些业务逻辑处理 判断用户状态是否正常判断用户余额是否充足。 这些业务逻辑都要在service层来做另外更新余额需要自定义 SQL要在mapper中来实现。因此我们除了要编写controller以外具体的业务还要在service和mapper中编写。 首先在UserController中定义一个方法 PostMapping({id}/deduct/{money}) ApiOperation(根据id扣减用户余额) public void deductBalanceById(PathVariable(id) Long id, PathVariable(money) Integer money){userService.deductBalanceById(id, money); }然后是UserService接口 public interface IUserService extends IServiceUser {void deductBalanceById(Long id, Integer money); }再然后是UserServiceImpl实现类 Service public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {Overridepublic void deductBalanceById(Long id, Integer money) {// 1. 查询用户User user getById(id);// 2. 判断用户状态if(user null || user.getStatus() 2){throw new RuntimeException(用户状态异常);}// 3. 判断用户余额if(user.getBalance() money){throw new RuntimeException(用户余额不足);}// 4. 扣减余额baseMapper.deductBalanceById(id, money);} }最后是 Mapper public interface UserMapper extends BaseMapperUser {Update(UPDATE user SET balance balance - #{money} WHERE id #{id})void deductBalanceById(Param(id) Long id, Param(money) Integer money); }3.4 Lambda 功能 IService接口中也提供了Lambda功能来简化我们的复杂查询及更新功能。让我们通过下面两个案例来了解一下如何使用这个 Lambda 功能。 案例一使用lambdaUpdate 改写上述扣减余额的功能 此时我们只需要修改 UserServiceImpl 中deductBalanceById方法的实现代码即可 Override public void deductBalanceById(Long id, Integer money) {// 1. 查询用户User user getById(id);// 2. 判断用户状态if(user null || user.getStatus() 2){throw new RuntimeException(用户状态异常);}// 3. 判断用户余额if(user.getBalance() money){throw new RuntimeException(用户余额不足);}// 4. 扣减余额int remainBalance user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance 0, User::getStatus, 2) // 如果用户余额为 0 就冻结.eq(User::getId, id).eq(User::getBalance, user.getBalance()) // CAS 乐观锁判断此期间用户余额是否被修改.update(); }此时可以直接使用 lambdaUpdate 来构造我们的SQL语句并在最后调用 update 执行这些SQL语句。对于上述代码有以下值得注意的地方 当用户的余额为 0 的时候就冻结该用户即改变 status 字段。注意set方法的第一个参数是一个条件判断语句如果该条件为真则在SQL执行该SET操作在执行update 操作之前使用乐观锁 CAS 来判断余额是否被修改保证在并发时的线程安全问题。 案例二使用 lambdaQuery 实现一个根据复杂条件查询用户的接口查询条件如下 name用户名关键字可以为空status用户状态可以为空minBalance最小余额可以为空maxBalance最大余额可以为空 可以将上述需求理解成一个用户的后台管理界面管理员可以自己选择条件来筛选用户因此上述条件不一定存在需要做判断。 此时由于前端的参数传入的可能性比较多因此就直接使用一个 UserQuery 的实体来进行接收 Data ApiModel(description 用户查询条件实体) public class UserQuery {ApiModelProperty(用户名关键字)private String name;ApiModelProperty(用户状态1-正常2-冻结)private Integer status;ApiModelProperty(余额最小值)private Integer minBalance;ApiModelProperty(余额最大值)private Integer maxBalance; }Controller 方法 GetMapping(/list) ApiOperation(根据复杂条件查询用户集合接口) public ListUserVO queryUsers(UserQuery userQuery){// 1. 查询 PO 对象集合ListUser users userService.queryUsers(userQuery);// 2. 将 PO 转换为 VO 并返回return BeanUtil.copyToList(users, UserVO.class); }IUserService接口 public interface IUserService extends IServiceUser {ListUser queryUsers(UserQuery userQuery); }UserServiceImpl实现类 Override public ListUser queryUsers(UserQuery userQuery) {String name userQuery.getName();Integer status userQuery.getStatus();Integer minBalance userQuery.getMinBalance();Integer maxBalance userQuery.getMaxBalance();return lambdaQuery().like(name ! null, User::getUsername, name).eq(status ! null, User::getStatus, status).ge(minBalance ! null, User::getBalance, minBalance).le(maxBalance ! null, User::getBalance, maxBalance).list(); }在链式编程的最后添加一个list()这是在告诉 MyBatis Plus 我们的调用结果需要是一个list集合。这里不仅可以用list()可选的方法有 .one()最多1个结果.list()返回集合结果.count()返回计数结果。 Mybatis Plus会根据链式编程的最后一个方法来判断最终的返回结果。
http://www.huolong8.cn/news/177636/

相关文章:

  • 在网站上做漂浮网站突然没收录
  • jsp网站开发详解下载网站建设需要ui吗
  • dw做网站时怎么在图片上加字化妆品网站制作需要
  • 多语种网站开发郑州网站优化哪家专业
  • winxp下做网站无锡手机网站建设服务
  • 个人摄影网站模版有什么网站建设比较好的公司
  • 石家庄营销型网站建设公司html字体代码大全
  • 合肥建设银行招聘网站重庆装修网
  • 中国建设银行网站评价门户类网站费用
  • 济南做公司网站网站不备案可以使用么
  • 中国设计之窗官方网站成都网站建设那家好
  • 易站通这个网站怎么做帮人做彩票网站支付接口
  • 漳州专业网站建设价格广州定制网站建设方案书
  • 网站维护的主要内容包括如何申请一个免费的网站空间
  • 制作网站网页网站源码后台
  • 电子网站商业策划书企业网站建设方案如何写
  • 个人博客网站教程响应式手机网站建设
  • 建瓯市建设银行网站博客
  • 毕设做音乐网站自建的电子网站如何做推广
  • 网站外包建设旅游公司网页设计
  • 电子商务物流网站建设h5收款平台
  • 孝感网站开发的公司微视看视频领红包下载安装
  • asp 网站路径泄露 解决深圳信科做网站
  • 外企网站建设公司秦皇岛市教育局官网
  • 江苏省城乡住房建设厅网站网络品牌营销推广
  • 档案网站建设优秀代表网站建设:宏智网络科技
  • 国内网站建设 必须实名认证3d建模教程
  • 东莞服装网站建设个人主页免费
  • 福州商城网站破解织梦做的网站
  • 潍坊兆通网站建设北京快速建站制作公司