1.不用写mapper.xml映射文件,让接口继承自basemapper即可。
数据库中表的字段必须和user类中的字段一摸一样,数据库中的表必须叫user
只能进行简单的crud操作。
package com.atguigu.rj1192.springboot630.mapper;import com.atguigu.rj1192.springboot630.pojo.User;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;//只需要继承自basemapper接口,就可以实现该方法
//数据库中有一个user表,对应我们的user类
//@Mapper
public interface UserMapper extends BaseMapper {
}
2.当实体类和表名不一致时,可以在实体类指定表名
package com.atguigu.rj1192.springboot630.pojo;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;@Data
@ToString
@TableName("users")//当实体类和表名不一致的时候,用@tablename来指定表名
public class User {@TableField(exist = false)public String tons;//类中有,但是表中没有的属性public int id;public String username;public String password;
}
2.service层
userservice接口要继承自IService
package com.atguigu.rj1192.springboot630.service.impl;import com.atguigu.rj1192.springboot630.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.stereotype.Service;import java.util.Collection;@Service
public interface UserService extends IService {}
Userserviceimpl实现类要继承自ServiceImpl
第一个参数代表要使用哪个mappper映射文件
第二个参数代表要操作的数据类型
package com.atguigu.rj1192.springboot630.service;import com.atguigu.rj1192.springboot630.mapper.UserMapper;
import com.atguigu.rj1192.springboot630.pojo.User;
import com.atguigu.rj1192.springboot630.service.impl.UserService;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
//第一个参数代表要使用哪个mappper映射文件
//第二个参数代表要操作的数据类型
public class UserServiceimpl extends ServiceImpl implements UserService{}
controller层调用的时候
@RequestMapping("/")public ModelAndView index() {ModelAndView mav = new ModelAndView();mav.setViewName("index");
// 将要查询出来的user类型的数据,转换成wrapper类型。QueryWrapper wrapper = new QueryWrapper<>();Collection users=userService.list(wrapper);mav.addObject("users", users);return mav;}
IdType.INPUT IdType.None 不自增 ,需要用户设置id,一般用input
IdType.ASSIGN_UUID varchar类型 IdType.ASSIGN_ID bigint类型 雪花算法生成随机id
插入新数据时不用管id,会自增的。
其他的主键自增方法还有:
1》mysql自增,缺点是如果做了分库分表,需要查询最大的id后,+1才能插入新数据,比较耗时间
2》uuid 缺点是无法排序,每次都生成唯一且随机的
3》redis集群 原子操作
@Data
public class User {
// IdType.INPUT IdType.None 不自增 ,需要用户设置id,一般用input
// IdType.ASSIGN_UUID varchar类型 IdType.ASSIGN_ID bigint类型 雪花算法生成随机id@TableId(type = IdType.ASSIGN_ID)private Long id;private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT)private Date createTime;// 添加和修改时都有值@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
}
(1)数据库表中添加自动填充字段
在User表中添加datetime类型的新的字段 create_time、update_time
(2)实体上添加注解
FieldFill.INSERT 在插入新数据时执行对应的方法(第三步定义)
FieldFill.INSERT_UPDATE 在插入和更新数据时执行对应的方法(第三步定义)
@Data
public class User {
// IdType.INPUT IdType.None 不自增 ,需要用户设置id,一般用input
// IdType.ASSIGN_UUID varchar类型 IdType.ASSIGN_ID bigint类型 雪花算法生成随机id@TableId(type = IdType.ASSIGN_ID)private Long id;private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT)private Date createTime;// 添加和修改时都有值@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
}
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);//使用mp执行添加操作,会执行@Overridepublic void insertFill(MetaObject metaObject) {//MetaObject 原数据对象 数据库名 表名等信息LOGGER.info("开始添加填充 ....");this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}// 使用mp执行更新操作,会执行@Overridepublic void updateFill(MetaObject metaObject) {LOGGER.info("开始更新填充 ....");this.setFieldValByName("updateTime", new Date(), metaObject);}}
(4)在修改和插入时就会自动填充修改时间和插入时间。
@Testvoid updateuser() {User user = new User();
// 不需要去设置id值,mp会帮我们自动生成id值user.setAge(555);user.setId(102l);// 返回结果是影响的行数System.out.println("修改影响的行数:" + userMapper.updateById(user));}
mike工资是五千 管理员a 要将工资修改为8000 管理员b要将工资减少两千
a和b同时修改,同时拿到修改前的5000
a修改工资为8000,提交事务。
a提交事务后,b修改工资5000-2000=3000,b将工资修改为3000
mike的工资变成了3000,而不是6000,就造成了丢失更新问题
乐观锁和悲观锁可以解决丢失更新问题
管理员a和b同时获得1版本,a修改完了提交,数据变成2版本,b修改完了提交,发现数据已经变成2版本了,则b管理员提交失败。
1》数据库中添加version字段 bigint类型
2》实体类中添加version字段,并添加@Version注解
并通过@TableField(fill = FieldFill.INSERT)设置添加新记录时给verison默认值1
@Data
public class User {// IdType.INPUT IdType.None 不自增 ,需要用户设置id,一般用input
// IdType.ASSIGN_UUID varchar类型 IdType.ASSIGN_ID bigint类型 雪花算法生成随机id@TableId(type = IdType.ASSIGN_ID)private Long id;private String name;private Integer age;private String email;@Version@TableField(fill = FieldFill.INSERT)private Integer version;@TableField(fill = FieldFill.INSERT)private Date createTime;// 添加和修改时都有值@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
}
设置添加新记录时给verison默认值1
this.setFieldValByName("version", 1, metaObject);
(上面添加新纪录时间自动填充的步骤一样)
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);//使用mp执行添加操作,会执行@Overridepublic void insertFill(MetaObject metaObject) {//MetaObject 原数据对象 数据库名 表名等信息LOGGER.info("开始添加填充 ....");this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);this.setFieldValByName("version", 1, metaObject);}// 使用mp执行更新操作,会执行@Overridepublic void updateFill(MetaObject metaObject) {LOGGER.info("开始更新填充 ....");this.setFieldValByName("updateTime", new Date(), metaObject);}
3》配置乐观锁插件
在mybatisplus设置类中 设置乐观锁插件
(在这个类中配置@mapperscan注解,这个注解尽量不写在启动类上,而是写在mp配置类中。)
@MapperScan("com.example.mp1229.mapper")
@Configuration
public class MPconfig {
// 乐观锁插件@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
4》需要先查询出来,再修改 在修改之后,会发现该数据的verision增加了1
//测试乐观锁@Testvoid testOptimisticLocker() {User user = userMapper.selectById(102l);
// 不需要去设置id值,mp会帮我们自动生成id值user.setAge(10);// 返回结果是影响的行数System.out.println("修改影响的行数:" + userMapper.updateById(user));}
模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了version
//测试乐观锁@Testvoid testOptimisticLocker() {User user = userMapper.selectById(102l);
// 不需要去设置id值,mp会帮我们自动生成id值user.setAge(10);
// 模拟取出数据后,数据库中version实际数据比取出的值大,即已被其它线程修改并更新了versionuser.setVersion(user.getVersion()-1);// 返回结果是影响的行数System.out.println("修改影响的行数:" + userMapper.updateById(user));}
6.逻辑删除
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
1)数据库中添加 deleted字段
2)mybatisplus实体类中添加deleted字段,并设置默认值 0 (未删除) 和上面一样。
user类
@TableField(fill = FieldFill.INSERT)private Integer deleted;
MyMetaObjectHandler类
//使用mp执行添加操作,会执行@Overridepublic void insertFill(MetaObject metaObject) {//MetaObject 原数据对象 数据库名 表名等信息LOGGER.info("开始添加填充 ....");this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);this.setFieldValByName("version", 1, metaObject);
// 添加新数据时,逻辑已删除值设置为0,未删除this.setFieldValByName("deleted",0,metaObject);}
3)application.yaml配置逻辑删除字段,删除和未删除对应的 逻辑值
mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名( 3.3.0 版本后,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
4)使用deletebyid 删除即可
@Testvoid logcaldel(){int result=userMapper.deleteById(1608419885151080450l);System.out.println("逻辑删除结果"+result);}
5)查询所有 会自动携带查询deleted为0的数据
@Test
void findall() {System.out.println(userMapper.selectList(null));
}

上一篇:【十分钟学懂Linux操作系统】