咸宁商城网站建设,wordpress正计时代码,怎么建网站教程视频app,wordpress安装配置2.核心功能
刚才的案例中都是以id为条件的简单CRUD#xff0c;一些复杂条件的SQL语句就要用到一些更高级的功能了。
2.1.条件构造器
除了新增以外#xff0c;修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外一些复杂条件的SQL语句就要用到一些更高级的功能了。
2.1.条件构造器
除了新增以外修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外还支持更加复杂的where条件。 参数中的Wrapper就是条件构造的抽象类其下有很多默认实现继承关系如图 Wrapper的子类AbstractWrapper提供了where中包含的所有条件构造方法 而QueryWrapper在AbstractWrapper的基础上拓展了一个select方法允许指定查询字段 而UpdateWrapper在AbstractWrapper的基础上拓展了一个set方法允许指定SQL中的SET部分
2.1.1.QueryWrapper
无论是修改、删除、查询都可以使用QueryWrapper来构建查询条件。接下来看一些例子
1.查询查询出名字中带o的存款大于等于1000元的人。代码如下
Test
void testQueryWrapper() {// 1.构建查询条件 where name like %o% AND balance 1000QueryWrapperUser wrapper new QueryWrapperUser().select(id, username, info, balance).like(username, o).ge(balance, 1000);// 2.查询数据ListUser users userMapper.selectList(wrapper);users.forEach(System.out::println);
}更新更新用户名为Jack的用户的余额为2000代码如下
Test
void testUpdateByQueryWrapper() {// 1.构建查询条件 where name JackQueryWrapperUser wrapper new QueryWrapperUser().eq(username, Jack);// 2.更新数据user中非null字段都会作为set语句User user new User();user.setBalance(2000);userMapper.update(user, wrapper);
}2.1.2.UpdateWrapper 基于BaseMapper中的update方法更新时只能直接赋值对于一些复杂的需求就难以实现。 例如更新id为1,2,4的用户的余额扣200对应的SQL应该是
UPDATE user SET balance balance - 200 WHERE id in (1, 2, 4)SET的赋值结果是基于字段现有值的这个时候就要利用UpdateWrapper中的setSql功能了 // 更新id为1,2,4的用户的余额扣200Testvoid testUpdateWrapper() {// ListLong ids new ArrayList(Arrays.asList(1L, 2L, 4L)); //JDK8 可以使用这种方式ListLong ids List.of(1L, 2L, 4L); // JDK9 之后才有的of方法// 1.生成SQLUpdateWrapperUser userUpdateWrapper new UpdateWrapperUser().setSql(balance balance -200).in(id, ids); // WHERE id in (1, 2, 4)// 2.更新注意第一个参数可以给null也就是不填更新字段和数据// 而是基于UpdateWrapper中的setSql来更新userMapper.update(null, userUpdateWrapper);}2.1.3.LambdaQueryWrapper
无论是QueryWrapper还是UpdateWrapper在构造条件的时候都需要写死字段名称会出现字符串魔法值。这在编程规范中显然是不推荐的。 那怎么样才能不写字段名又能知道字段名呢
其中一种办法是基于变量的gettter方法结合反射技术。因此我们只要将条件对应的字段的getter方法传递给MybatisPlus它就能计算出对应的变量名了。而传递方法可以使用JDK8中的方法引用和Lambda表达式。 因此MybatisPlus又提供了一套基于Lambda的Wrapper包含两个 -LambdaQueryWrapper
LambdaUpdateWrapper 分别对应QueryWrapper和UpdateWrapper
其使用方式如下 Testvoid testLambdaQueryWrapper() {// 1.构建查询条件 where name like %o% AND balance 1000LambdaQueryWrapperUser userLambdaQueryWrapper new LambdaQueryWrapperUser().select(User::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, o).ge(User::getBalance, 1000);// 2.查询数据ListUser users userMapper.selectList(userLambdaQueryWrapper);users.forEach(System.out::println);}// 更新用户名为jack的用户的余额为2000Testvoid testLambdaUpdateByQueryWrapper() {// 1.构建查询条件 where name JackLambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser().eq(User::getUsername, Jack);// 2.更新数据user中非null字段都会作为set语句User user new User();user.setBalance(2000);userMapper.update(user, wrapper);}2.2.自定义SQL
在演示UpdateWrapper的案例中我们在代码中编写了更新的SQL语句 这种写法在某些企业也是不允许的因为SQL语句最好都维护在持久层而不是业务层。就当前案例来说由于条件是in语句只能将SQL写在Mapper.xml文件利用foreach来生成动态SQL。 这实在是太麻烦了。假如查询条件更复杂动态SQL的编写也会更加复杂。
所以MybatisPlus提供了自定义SQL功能可以让我们利用Wrapper生成查询条件再结合Mapper.xml编写SQL
2.2.1.基本用法
以当前案例来说我们可以这样写
Test
void testCustomWrapper() {// 1.准备自定义查询条件ListLong ids List.of(1L, 2L, 4L);QueryWrapperUser wrapper new QueryWrapperUser().in(id, ids);// 2.调用mapper的自定义方法直接传递WrapperuserMapper.deductBalanceByIds(200, wrapper);
}然后在UserMapper中自定义SQL
package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Param;public interface UserMapper extends BaseMapperUser {Select(UPDATE user SET balance balance - #{money} ${ew.customSqlSegment})void deductBalanceByIds(Param(money) int money, Param(ew) QueryWrapperUser wrapper);
}这样就省去了编写复杂查询条件的烦恼了。
总结 在mapper方法参数中用Param注解声明wrapper变量名称必须是ew。 为什么必须要用ewmybatisPlus 源码规定的,这也成为一种约定俗成的规范。当然你也可以手动修改生成的代码将 ew 改为其他名字但这样可能导致一些示例代码不适用。 2.2.2.多表关联
理论上来讲MyBatisPlus是不支持多表查询的不过我们可以利用Wrapper中自定义条件结合自定义SQL来实现多表查询的效果。 例如我们要查询出所有收货地址在北京的并且用户id在1、2、4之中的用户 要是自己基于mybatis实现SQL大概是这样的
select idqueryUserByIdAndAddr resultTypecom.itheima.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 testCustomJoinWrapper() {// 1.准备自定义查询条件QueryWrapperUser wrapper new QueryWrapperUser().in(u.id, List.of(1L, 2L, 4L)).eq(a.city, 北京);// 2.调用mapper的自定义方法ListUser users userMapper.queryUserByWrapper(wrapper);users.forEach(System.out::println);
}然后在UserMapper中自定义方法
Select(SELECT u.* FROM user u INNER JOIN address a ON u.id a.user_id ${ew.customSqlSegment})
ListUser queryUserByWrapper(Param(ew)QueryWrapperUser wrapper);当然也可以在UserMapper.xml中写SQL
select idqueryUserByWrapper resultTypecom.itheima.mp.domain.po.UserSELECT * FROM user u INNER JOIN address a ON u.id a.user_id ${ew.customSqlSegment}
/select2.3.Service接口
MybatisPlus不仅提供了BaseMapper还提供了通用的Service接口及默认实现封装了一些常用的service模板方法。 通用接口为IService默认实现为ServiceImpl其中封装的方法可以分为以下几类
save新增remove删除update更新get查询单个结果list查询集合结果count计数page分页查询
2.3.1.CRUD
我们先俩看下基本的CRUD接口。
新增 save是新增单个元素saveBatch是批量新增saveOrUpdate是根据id判断如果数据存在就更新不存在则新增saveOrUpdateBatch是批量的新增或修改
删除 removeById根据id删除removeByIds根据id批量删除removeByMap根据Map中的键值对为条件删除remove(WrapperT)根据Wrapper条件删除removeBatchByIds暂不支持
修改
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条件的数据数量
getBaseMapper
当我们在service中要调用Mapper中自定义SQL时就必须获取service对应的Mapper就可以通过这个方法
项目结构如下 来到 UserService 中创建 测试类 接下来我们快速实现下面4个接口
首先我们在项目中引入几个依赖 pom.xml
!--swagger--
dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-openapi2-spring-boot-starter/artifactIdversion4.1.0/version
/dependency
!--web--
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId
/dependency然后在application.xml需要配置swagger信息
knife4j:enable: trueopenapi:title: 用户管理接口文档description: 用户管理接口文档email: zhanghuyiitcast.cnconcat: 墨苒孤url: https://www.itcast.cnversion: v1.0.0group:default:group-name: defaultapi-rule: packageapi-rule-resources:- com.itheima.mp.controllerAlt 8 选择 springboot 服务启动浏览器输入 http://localhost:8080/doc.html#/home 然后接口需要两个实体
UserFormDTO代表新增时的用户表单UserVO代表查询的返回结果 首先是UserFormDTO
package com.itheima.mp.domain.dto;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;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
package com.itheima.mp.domain.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;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;
}用 Autowired 注入Spring 并不推荐而是推荐我们使用构造函数注入 构造函数注入如下 但是这样会带来一个问题如果成员很多构造函数就会很多看起来很繁琐。那么就可以使用Lombok 注解帮我们简化 上图这样看起来是可以了但是一个类可以有很多的成员并不是每一个都是需要注入的。那么怎么区分哪些需要注入哪些不需要注入呢 可以给 成员 加上 final 来区分, 这样就必须在类初始化的时候对加了 final的成员进行初始化所以最终写法如下 RequiredArgsConstructor表示 会对 final 修饰的成员进行创建构造函数没有修饰就不会生成构造函数
新增接口实现
PostMappingApiOperation(新增用户)public void saveUser(RequestBody UserFormDTO userFormDTO) {// 1.转换DTO为POUser user BeanUtil.copyProperties(userFormDTO, User.class);// 2.新增userService.save(user);}由于传入的 是 DTO, 而我们需要保存的是 PO,所以需要先把DTO转换为PO。这里使用胡图工具包其余接口同理 DeleteMapping(/{id})ApiOperation(删除用户)public void removeUserById(PathVariable(id) Long userId){userService.removeById(userId);}GetMapping(/{id})ApiOperation(根据id查询用户)public UserVO queryUserById(PathVariable(id) Long userId){// 1.查询用户User user userService.getById(userId);// 2.处理po转voreturn BeanUtil.copyProperties(user, UserVO.class);}GetMappingApiOperation(根据id集合查询用户)public ListUserVO queryUserByIds(RequestParam(ids) ListLong ids){// 1.查询用户ListUser users userService.listByIds(ids);// 2.处理po转vo 集合用copyToListreturn BeanUtil.copyToList(users, UserVO.class);}代码在github https://github.com/RanGuMo/mp-demo