青岛即墨网站建设设计,静态网页怎么放到网上,连云港网站开发,建设局与住建局的区别代码生成
使用MP的步骤是非常固定的几步操作 基于插件, 可以快速的生成基础性的代码 安装插件安装完成后重启IEDA连接数据库 mp是数据库的名字?serverTimezoneUTC 是修复mysql时区, 不加会报错
生成代码 TablePrefix选项是用于去除表名的前缀, 比如根据tb_user表生成实体类U…代码生成
使用MP的步骤是非常固定的几步操作 基于插件, 可以快速的生成基础性的代码 安装插件安装完成后重启IEDA连接数据库 mp是数据库的名字?serverTimezoneUTC 是修复mysql时区, 不加会报错
生成代码 TablePrefix选项是用于去除表名的前缀, 比如根据tb_user表生成实体类User, 就填写tb_
静态工具
业务开发中, 可能会存在service之间互相调用, 如果使用传统的资源注入, 就会出现循环依赖的问题
建议就是service之间的相互调用, 使用DB静态工具进行方法的调用, 避免循环依赖的问题
DB静态工具的方法和IService的方法几乎一样, 只是调用时需要传入字节码 案例1: 改造根据id查询用户的接口, 查询用户的同时, 查询出对应的地址
/*** author * since 2023-07-01*/
Data
ApiModel(description 收货地址VO)
public class AddressVO{ApiModelProperty(id)private Long id;ApiModelProperty(用户ID)private Long userId;ApiModelProperty(省)private String province;ApiModelProperty(市)private String city;ApiModelProperty(县/区)private String town;ApiModelProperty(手机)private String mobile;ApiModelProperty(详细地址)private String street;ApiModelProperty(联系人)private String contact;ApiModelProperty(是否是默认 1默认 0否)private Boolean isDefault;ApiModelProperty(备注)private String notes;
}Data
ApiModel(description 用户VO实体)
public class UserVO {ApiModelProperty(用户id)private Long id;ApiModelProperty(用户名)private String username;ApiModelProperty(详细信息)private String info;ApiModelProperty(使用状态1正常 2冻结)private UserStatus status;ApiModelProperty(账户余额)private Integer balance;ApiModelProperty(用户的收货地址)private ListAddressVO addresses;}
Api(tags 用户管理接口)
RequestMapping(/users)
RestController
RequiredArgsConstructor
public class UserController {private final IUserService userService;ApiOperation(根据id查询用户接口)GetMapping(/{id})public UserVO queryUserById(ApiParam(用户id) PathVariable(id) Long id){return userService.queryUserAndAddressById(id);}
}
public interface IUserService extends IServiceUser {UserVO queryUserAndAddressById(Long id);}
Service
public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {Overridepublic UserVO queryUserAndAddressById(Long id) {//1,查询用户User user getById(id);if (user null || user.getStatus() UserStatus.FROZEN) {throw new RuntimeException(用户状态异常);}//2查询地址ListAddress addresses Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();//3封装VO//3.1把user的PO转成VOUserVO userVO BeanUtil.copyProperties(user, UserVO.class);//3.2转地址为VOif (CollUtil.isNotEmpty(addresses)) {userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));}return userVO;}} 案例2: 改造根据id批量查询的接口, 查询用户的同时, 查询出用户对应的所有地址
Api(tags 用户管理接口)
RequestMapping(/users)
RestController
RequiredArgsConstructor
public class UserController {private final IUserService userService;ApiOperation(根基id批量查询用户接口)GetMappingpublic ListUserVO queryUserByIds(ApiParam(用户id集合) RequestParam(ids) ListLong ids) {return userService.queryUserAndAddressByIds(ids);}}
public interface IUserService extends IServiceUser {ListUserVO queryUserAndAddressByIds(ListLong ids);}
Service
public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {Overridepublic ListUserVO queryUserAndAddressByIds(ListLong ids) {//1,查询用户ListUser users listByIds(ids);if (CollUtil.isNotEmpty(users)) {return Collections.emptyList();}//2,查询地址//2.1获取用户id集合ListLong userIds users.stream().map(User::getId).collect(Collectors.toList());//2.2根据用户id查询地址ListAddress addresses Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();//2.3转换地址VOListAddressVO addressVOList BeanUtil.copyToList(addresses, AddressVO.class);//2.4用户地址集合分组处理, 相同用户的放入一个集合(组)中MapLong, ListAddressVO addressMap new HashMap(0);if (CollUtil.isNotEmpty(addressVOList)) {addressMap addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));}//3,转换VO返回ListUserVO list new ArrayList(users.size());for (User user : users) {//3.1转换USER的PO为VOUserVO vo BeanUtil.copyProperties(user, UserVO.class);list.add(vo);//3.2转换地址VOvo.setAddresses(addressMap.get(user.getId()));}return list;}}
逻辑删除
逻辑删除就是基于代码逻辑, 模拟删除效果, 不会真正删除数据
在表中添加一个字段标记数据是否被删除当删除数据时把标记置为1 查询时只查询标记为0的数据 MP提供了逻辑删除功能, 无需改变方法调用的方式, 只需要简单配置, MP就会在底层自动修改CRUE的语句 在application.yaml文件中配置逻辑删除的字段名称和值就可以 案例
mybatis-plus:type-aliases-package: com.itheima.mp.domain.poglobal-config:db-config:logic-delete-field: deleted # 配置逻辑删除字段
SpringBootTest
class IAddressServiceTest {Autowiredprivate IAddressService addressService;Testvoid testLogicDelete() {//1,删除addressService.removeById(59L); // 代码是正常删除,但执行的是更新操作,更新deleted字段//2,查询Address address addressService.getById(59L);System.out.println(address address); // null,已经删除的数据查不到}
} 逻辑删除存在的问题:
会导致数据表中的垃圾数据越来越多, 影响查询效率SQL中全都要对逻辑删除字段进行判断,影响查询效率 其他方案
如果数据不能删除, 可以把在删除之前, 把数据迁移到备份的表中,然后执行删除操作, 这样主表中的数据就比较干净, 而且数据也会保留
枚举处理器
作用: 解决java的enum类型和数据库INT类型的相互转换问题 开发过程中, 我们会使用枚举类型 替换 固定数值但数据表中存储的字段依然是整数类型所以java实体类中和数据库中数据类型要相互转换 原理: MP提供了枚举类型处理器, 用于自动转换实体类的枚举类型 存储数据: 自动把枚举类型转成INT类型存入数据库封装数据: 自动把数据库INT类型数据转成枚举类型保存 配置全局枚举处理器, 让枚举处理器生效
mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler 给枚举类添加注解, 告诉MP要对哪个成员变量进行类型处理
Getter
public enum UserStatus {NORMAL(1, 正常),FROZEN(2, 冻结),;EnumValue // 指定写入数据库的数据private final int value;JsonValue // 指定返回前端的数据private final String desc;UserStatus(int value, String desc) {this.value value;this.desc desc;}
}
枚举做JSON处理时, 默认会以枚举项的名字返回如果想以value或者desc返回, 可以通过注解告诉SpringMVC要返回那个值 在实体类中使用枚举类型
Data
ApiModel(description 用户VO实体)
public class UserVO {... ...ApiModelProperty(使用状态1正常 2冻结)// private Integer status;private UserStatus status;
}
Data
TableName(value user,autoResultMap true)
public class User {... .../*** 使用状态1正常 2冻结*/private UserStatus status;
} 业务代码中, 愉快的使用枚举替代魔法数值
Service
public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {OverrideTransactionalpublic void deductBalance(long id, Integer money) {//1,查询用户User user getById(id);//2,校验用户状态if (user null || user.getStatus() UserStatus.FROZEN) {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).eq(User::getId, id).eq(User::getBalance, user.getBalance()) // 乐观锁.update();}
}
JSON处理器
问题说明 user表中有一个info字段是json类型, java中没有对应的数据类型, 通常用字符串类型接收MuBatis可以自动进行字符串和JSON的转换使用字符串接收JSON类型数据, 从数据库的操作层面是没有问题, 增删改查都是正常的但是从业务层面就会出现麻烦, 比如需要取出info中的age信息, 处理起来就比较麻烦 MP提供了JSON类型处理器, 可以把java对象和数据库的JSON对象 相互转换 SpringMVC使用的JacksonJSON处理器使用JacksonTypeHandler不需要额外引用依赖 使用JSON处理器的步骤 使用 TableField() 注解, 指定并开启JSON处理器使用JSON数据后, 就出现了对象嵌套对象的情况, User对象嵌套UserInfo对象就要开启自动结果映射 autoResultMap true 实际操作
Data
NoArgsConstructor
AllArgsConstructor(staticName of)
public class UserInfo {private Integer age;private String intro;private String gender;
}
定义PO对象封装JSON数据 Data
TableName(value user,autoResultMap true)
public class User {... .../*** 详细信息*/TableField(typeHandler JacksonTypeHandler.class)// private String info;private UserInfo info;}
使用java对象替代String接收数据库数据使用TableField()注解开启JSON处理器设置autoResultMap true, 开启自动结果映射查询结果对比