一、使用Mybatis-plus时为什么要配置?
其实这很简单,因为当我们使用Mybatis-plus时,所有的sql都是不可见的,当我们想要知道它是怎样执行的时候,我们就需要看日志!
二、如何配置日志?
在application.properties中进行日志的配置
#配置日志,这里我选择默认的控制台输出,不管选择什么日志,都需要导包的
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
三、控制台的输出
总结: 不管选择什么日志,都需要导包;在application.properties中进行日志的配置!
四、插入测试
-
CRUD的扩展
- insert
//测试插入功能
@Test
public void testInsert(){
User user = new User();
user.setName( "来一沓java" );
user.setAge( 18 );
user.setEmail( "[email protected]" );
int insert = userMapper.insert( user );//帮我们自动设置id
System.out.println(insert);//受影响的行数
System.out.println("--------");
System.out.println(user);
}
运行的截图
数据库插入的id的默认值:全局唯一id
主键生成的策略
在实体类中的主键上面添加注解
@Data
public class User {
@TableId(type = IdType.AUTO)
//默认ID_WORKER:是全局唯一id
//AUTO:主键自增策略,这里一定要注意数据库中的主键字段一定得是自增的!
//NONE:未设置主键
//INPUT:手动输入
//UUID:全局唯一id uuid
//ID_WORKER_STR:ID_WORKER的字符串表示法
private Long id;
private String name;
private Integer age;
private String email;
}
可以看到,当我们设置主键自增以后删除刚才插入的数据 id就变为6了
update
//测试更新
@Test
public void testUpdate(){
User user = new User();
//通过条件自动拼接动态sql
long l = 6;
user.setId( l );
user.setName( "我爱学习" );
int i = userMapper.updateById( user );
System.out.println(i);
}
所有的动态sql都是Mybatis-plus自动给我们动态配置的!
自动填充
比如创建时间、修改时间这些操作一般都是自动化完成的,我们不需要手动完成。看过阿里巴巴开发手册的人应该都知道所有的数据库表都必须用到两个字段【gmt_create和gmt_modifed】
自动填充方式一:数据库级别
在表中新增上面两个字段gmt_create和gmt_modifed
同步实体类,并再次测试插入
@Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; private Date gmtCreate; private Date gmtModifed; }
自动填充方式二:代码级别
1.首先删除数据库的默认值,更新操作,在这里我们需要在实体类字段属性上添加注解
@TableField(fill = FieldFill.INSERT) //INSERT:插入和更新的时候自动填充 private Date gmtCreate; @TableField(fill = FieldFill.INSERT_UPDATE) //INSERT_UPDATE:插入和更新的时候自动填充 private Date gmtModifed;
2.编写一个处理器来处理这个注解即可
@Slf4j @Component //这里是把处理器加到IOC容器中 public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) {//插入时的填充策略 log.info( "start insert fill ....." ); this.setFieldValByName( "gmtCreate",new Date(),metaObject ); this.setFieldValByName( "gmtModifed",new Date(),metaObject ); } @Override public void updateFill(MetaObject metaObject) {//更新时的填充策略 log.info( "start update fill ....." ); this.setFieldValByName( "gmtModifed",new Date(),metaObject ); } }
3.再次执行之前的插入和更新操作
查询操作
//测试单个查询
@Test
public void testSelectById(){
User user = userMapper.selectById( 1 );
System.out.println(user);
}
//查询批量用户
@Test
public void testSelectByBatchId(){
List<User> users = userMapper.selectBatchIds( Arrays.asList( 1, 2, 3 ) );
for (User user:users){
System.out.println(user);
}
}
//条件查询 map
@Test
public void testSelectByBatchIds(){
HashMap<String, Object> map = new HashMap<>();
//自定义查询
map.put( "name","来一沓Java" );
List<User> users = userMapper.selectByMap( map );
users.forEach( System.out::println);
}
4.删除操作
//单个删除
@Test
public void testDelete1(){
userMapper.deleteById( (long)1 );
}
//批量删除
@Test
public void testDelete2(){
userMapper.deleteBatchIds( Arrays.asList( 3,4 ) );
}
//条件删除
@Test
public void testDelete3(){
HashMap<String, Object> map = new HashMap<>();
map.put( "name","我爱学习2" );
userMapper.deleteByMap( map );
}
五、雪花算法
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。这样几乎可以保证全球唯一了。
六、乐观锁
乐观锁:它总认为不会出现问题,不管做什么都不加锁,如果出现问题,就会再次更新值测试!【有新version和new version,每次都会判断版本号是否更新了】
悲观锁:它总是认为总是会出现问题,不管做什么都加锁,再去操作!
七、乐观锁机制
乐观锁实现方式
- 取出记录时,获取当前版本号
- 更新时,带上这个version
- 执行时更新时,set version=newVersion where version = oldVersion
- 如果version不对,就会执行失败
update user set name = "来一沓java",version = version + 1 where id = 2 and version = 1
乐观锁第一步回先查询,获得版本号
比如说两个线程A和B,A和B同时执行上面的sql语句,B在A之前完成,那么version变为了2,此时A就会执行失败!
测试乐观锁插件
1.数据库表增加字段version
2.完善实体类
@Version //是乐观锁version的注解
private Integer version;
3.注册组件
@EnableTransactionManagement //自动管理事务,默认开启
@MapperScan("com.rxj.mapper") //扫描mapper文件夹
@Configuration //配置类
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4.测试乐观锁
测试成功
@Test
public void testOptimisticLocker(){
//查询用户信息
User user = userMapper.selectById( 1 );
//修改用户信息
user.setAge( 11 );
user.setEmail( "[email protected]" );
//更新操作
int i = userMapper.updateById( user );
System.out.println(i);
}
测试失败
@Test
public void testOptimisticLocker1(){
User user1 = userMapper.selectById( 1 );
user1.setAge( 4 );
user1.setEmail( "[email protected]" );
User user2 = userMapper.selectById( 1 );
user2.setAge( 5 );
user2.setEmail( "[email protected]" );
int i = userMapper.updateById( user2 );//如果没有乐观锁就会覆盖插队线程的值
//自旋锁来多次尝试提交
int i1 = userMapper.updateById( user1 );
}
可以看到数据库中id为1的年龄只更新为5,并没有更新为4,在这里我们一般会使用自旋锁多次尝试提交!
八、项目全局截图