mybatis_plus
(1)测试
自动拼接sql语句
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b48e183] was not registered for synchronization because synchronization is not active
2021-04-19 16:18:05.070 INFO 3268 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-04-19 16:18:05.474 INFO 3268 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@526874139 wrapping com.mysql.jdbc.JDBC4Connection@5a034157] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=? WHERE id=?
==> Parameters: 小天(String), 18(Integer), 7(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b48e183]
(2)自动填充
创建时间,修改时间 自动化完成,不需要手动更新
阿里巴巴开发手册:gmt_create,gmt_modified
几乎所有的表都要配置,自动化
数据库级别
1)在表中新增字段(需要设置timestamp类型)
create_time,create_user
private Date createTime;
private Date updateTime;
代码级别
(1)修改数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wb1l7XfR-1618826102816)(C:\Users\root\AppData\Roaming\Typora\typora-user-images\image-20210419164641845.png)]
(2)添加注解
package com.example.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private int age;
private String email;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//开始的时候两个字段都要有内容
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
(3)编写处理器来处理这个注解
package com.example.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
//加到ioc容器中
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill...");
// default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
this.setFieldValByName("createTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill...");
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
(4)结果
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a6f6c7e] was not registered for synchronization because synchronization is not active
2021-04-19 17:01:25.588 INFO 8220 --- [ main] com.example.handler.MyMetaObjectHandler : start update fill...
2021-04-19 17:01:25.597 INFO 8220 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-04-19 17:01:25.925 INFO 8220 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1679401185 wrapping com.mysql.jdbc.JDBC4Connection@280d4882] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, update_time=? WHERE id=?
==> Parameters: 李继(String), 68(Integer), 2021-04-19 17:01:25.588(Timestamp), 7(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a6f6c7e]
2021-04-1
(5)插入
==> Preparing: INSERT INTO user ( name, age, create_time, update_time ) VALUES ( ?, ?, ?, ? )
> Parameters: 曹钦(String), 23(Integer), 2021-04-19 17:04:19.321(Timestamp), null
< Updates: 1
mysql 锁 CAS
乐观锁
他总认为不会出现问题,无论干什么都不会加锁,出了问题再次更新值测试
悲观锁
他总是认为会出现问题,无论干什么都会上锁再去操作
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
测试MP乐观锁插件
(1)添加数据库字段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZ7GaI1F-1618826102818)(C:\Users\root\AppData\Roaming\Typora\typora-user-images\image-20210419173035953.png)]
(2)增加数据库字段到pojo
@Version
private Integer version;
(3)注册组件
package com.example.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
//自动管理事务,默认管理了
//
@MapperScan("com.example.mapper")
@EnableTransactionManagement
public class MybatisPlusConfig {
//注册
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
(4)测试
成功
//测试乐观锁
//成功
@Test
public void success() {
//查询用户信息
User user = userMapper.selectById(1);
//单线程修改
user.setName("zrm");
user.setEmail("1677");
int i = userMapper.updateById(user);
System.out.println(i);
}JDBC Connection [HikariProxyConnection@805536380 wrapping com.mysql.jdbc.JDBC4Connection@38f77cd9] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: zrm(String), 68(Integer), 1677(String), 2021-04-19 17:43:02.346(Timestamp), 2(Integer), 1(Long), 1(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6aa3bfc]
失败
//失败(多线程会失败)
@Test
public void fail() {
User user1 = userMapper.selectById(1);
//单线程修改
user1.setName("于洪111");
user1.setEmail("28999111");
//模拟另外一个线程插队操作
User user2 = userMapper.selectById(1);
//单线程修改
user2.setName("于洪222");
user2.setEmail("28999222");
//另一个线程抢先完成更新
userMapper.updateById(user2);
//如果没有乐观锁会覆盖抢完更新的值
//可以尝试自旋锁来尝试多次提交
userMapper.updateById(user1);
}
```## mybatis_plus
(1)测试
自动拼接sql语句
```sql
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b48e183] was not registered for synchronization because synchronization is not active
2021-04-19 16:18:05.070 INFO 3268 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-04-19 16:18:05.474 INFO 3268 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@526874139 wrapping com.mysql.jdbc.JDBC4Connection@5a034157] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=? WHERE id=?
==> Parameters: 小天(String), 18(Integer), 7(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3b48e183]
(2)自动填充
创建时间,修改时间 自动化完成,不需要手动更新
阿里巴巴开发手册:gmt_create,gmt_modified
几乎所有的表都要配置,自动化
数据库级别
1)在表中新增字段(需要设置timestamp类型)
create_time,create_user
private Date createTime;
private Date updateTime;
代码级别
(1)修改数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u49vbG52-1618826103976)(C:\Users\root\AppData\Roaming\Typora\typora-user-images\image-20210419164641845.png)]
(2)添加注解
package com.example.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private int age;
private String email;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//开始的时候两个字段都要有内容
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
(3)编写处理器来处理这个注解
package com.example.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
//加到ioc容器中
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill...");
// default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
this.setFieldValByName("createTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill...");
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
(4)结果
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a6f6c7e] was not registered for synchronization because synchronization is not active
2021-04-19 17:01:25.588 INFO 8220 --- [ main] com.example.handler.MyMetaObjectHandler : start update fill...
2021-04-19 17:01:25.597 INFO 8220 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-04-19 17:01:25.925 INFO 8220 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1679401185 wrapping com.mysql.jdbc.JDBC4Connection@280d4882] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, update_time=? WHERE id=?
==> Parameters: 李继(String), 68(Integer), 2021-04-19 17:01:25.588(Timestamp), 7(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a6f6c7e]
2021-04-1
(5)插入
==> Preparing: INSERT INTO user ( name, age, create_time, update_time ) VALUES ( ?, ?, ?, ? )
> Parameters: 曹钦(String), 23(Integer), 2021-04-19 17:04:19.321(Timestamp), null
< Updates: 1
mysql 锁 CAS
乐观锁
他总认为不会出现问题,无论干什么都不会加锁,出了问题再次更新值测试
悲观锁
他总是认为会出现问题,无论干什么都会上锁再去操作
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
测试MP乐观锁插件
(1)添加数据库字段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaiHT8JJ-1618826103980)(C:\Users\root\AppData\Roaming\Typora\typora-user-images\image-20210419173035953.png)]
(2)增加数据库字段到pojo
@Version
private Integer version;
(3)注册组件
package com.example.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
//自动管理事务,默认管理了
//
@MapperScan("com.example.mapper")
@EnableTransactionManagement
public class MybatisPlusConfig {
//注册
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
(4)测试
成功
//测试乐观锁
//成功
@Test
public void success() {
//查询用户信息
User user = userMapper.selectById(1);
//单线程修改
user.setName("zrm");
user.setEmail("1677");
int i = userMapper.updateById(user);
System.out.println(i);
}JDBC Connection [HikariProxyConnection@805536380 wrapping com.mysql.jdbc.JDBC4Connection@38f77cd9] will not be managed by Spring
==> Preparing: UPDATE user SET name=?, age=?, email=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: zrm(String), 68(Integer), 1677(String), 2021-04-19 17:43:02.346(Timestamp), 2(Integer), 1(Long), 1(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6aa3bfc]
失败
//失败(多线程会失败)
@Test
public void fail() {
User user1 = userMapper.selectById(1);
//单线程修改
user1.setName("于洪111");
user1.setEmail("28999111");
//模拟另外一个线程插队操作
User user2 = userMapper.selectById(1);
//单线程修改
user2.setName("于洪222");
user2.setEmail("28999222");
//另一个线程抢先完成更新
userMapper.updateById(user2);
//如果没有乐观锁会覆盖抢完更新的值
//可以尝试自旋锁来尝试多次提交
userMapper.updateById(user1);
}