目錄
一、insert
1、插入操作
@RunWith(SpringRunner.class)
@SpringBootTest
public class CRUDTests {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert(){
User user = new User();
user.setName("Helen");
user.setAge(18);
user.setEmail("[email protected]");
int result = userMapper.insert(user);
System.out.println(result); //影響的行數
System.out.println(user); //id自動回填
}
}
注意:數據庫插入id值默認爲:全局唯一id
2、主鍵策略
(1)ID_WORKER
MyBatis-Plus默認的主鍵策略是:ID_WORKER 全局唯一ID
參考資料:分佈式系統唯一ID生成方案彙總:https://www.cnblogs.com/haoxinyue/p/5208136.html
- 要想主鍵自增需要配置如下主鍵策略
- 需要在創建數據表的時候設置主鍵自增
- 實體字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO) private Long id;
要想影響所有實體的配置,可以設置全局主鍵配置
#全局設置主鍵生成策略
mybatis-plus.global-config.db-config.id-type=auto
其它主鍵策略:分析 IdType 源碼可知
@Getter
public enum IdType {
/**
* 數據庫ID自增
*/
AUTO(0),
/**
* 該類型爲未設置主鍵類型
*/
NONE(1),
/**
* 用戶輸入ID
* 該類型可以通過自己註冊自動填充插件進行填充
*/
INPUT(2),
/* 以下3種類型、只有當插入對象ID 爲空,才自動填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private int key;
IdType(int key) {
this.key = key;
}
}
二、update
1、根據Id更新操作
@Test
public void testUpdateById(){
User user = new User();
user.setId(1L);
user.setAge(28);
int result = userMapper.updateById(user);
System.out.println(result);
}
2、自動填充
項目中經常會遇到一些數據,每次都使用相同的方式填充,例如記錄的創建時間,更新時間等。
我們可以使用MyBatis Plus的自動填充功能,完成這些字段的賦值工作:
(1)數據庫表中添加自動填充字段
在User表中添加datetime類型的新的字段 create_time、update_time
(2)實體上添加註解
@Data
public class User {
......
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//@TableField(fill = FieldFill.UPDATE)
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
(3)實現元對象處理器接口
注意:不要忘記添加 @Component 註解
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(MyMetaObjectHandler.class);
@Override
public void insertFill(MetaObject metaObject) {
LOGGER.info("start insert fill ....");
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
LOGGER.info("start update fill ....");
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
3、樂觀鎖
主要適用場景:當要更新一條記錄的時候,希望這條記錄沒有被別人更新,也就是說實現線程安全的數據更新
樂觀鎖實現方式:
- 取出記錄時,獲取當前version
- 更新時,帶上這個version
- 執行更新時, set version = newVersion where version = oldVersion
- 如果version不對,就更新失敗
(1)數據庫中添加version字段
ALTER TABLE `user` ADD COLUMN `version` INT
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
(3)元對象處理器接口添加version的insert默認值
@Override
public void insertFill(MetaObject metaObject) {
......
this.setFieldValByName("version", 1, metaObject);
}
特別說明:
- 支持的數據類型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整數類型下
newVersion = oldVersion + 1
newVersion
會回寫到entity
中- 僅支持
updateById(id)
與update(entity, wrapper)
方法 - 在
update(entity, wrapper)
方法下,wrapper
不能複用!!!
@EnableTransactionManagement
@Configuration
@MapperScan("com.atguigu.mybatis_plus.mapper")
public class MybatisPlusConfig {
/**
* 樂觀鎖插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
(5)測試樂觀鎖可以修改成功
測試後分析打印的sql語句,將version的數值進行了加1操作
/**
* 測試 樂觀鎖插件
*/
@Test
public void testOptimisticLocker() {
//查詢
User user = userMapper.selectById(1L);
//修改數據
user.setName("Helen Yao");
user.setEmail("[email protected]");
//執行更新
userMapper.updateById(user);
}
此時數據庫中的version版本也變爲了2
三、select
1、根據id查詢記錄
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
2、通過多個id批量查詢
完成了動態sql的foreach的功能
@Test
public void testSelectBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
3、簡單的條件查詢
通過map封裝查詢條件
@Test
public void testSelectByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
注意:map中的key對應的是數據庫中的列名。例如數據庫user_id,實體類是userId,這時map的key需要填寫user_id
4、分頁
MyBatis Plus自帶分頁插件,只要簡單的配置即可實現分頁功能
(1)在配置類中添加插件
/**
* 分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
@Test
public void testSelectPage() {
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
System.out.println(page.getCurrent());
System.out.println(page.getPages());
System.out.println(page.getSize());
System.out.println(page.getTotal());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
控制檯sql語句打印:SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5
(3)測試selectMapsPage分頁:結果集是Map
@Test
public void testSelectMapsPage() {
Page<User> page = new Page<>(1, 5);
IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page, null);
//注意:此行必須使用 mapIPage 獲取記錄列表,否則會有數據類型轉換錯誤
mapIPage.getRecords().forEach(System.out::println);
System.out.println(page.getCurrent());
System.out.println(page.getPages());
System.out.println(page.getSize());
System.out.println(page.getTotal());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
四、delete
1、根據id刪除記錄
Test
public void testDeleteById(){
int result = userMapper.deleteById(8L);
System.out.println(result);
}
2、批量刪除
@Test
public void testDeleteBatchIds() {
int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
System.out.println(result);
}
3、簡單的條件查詢刪除
@Test
public void testDeleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
int result = userMapper.deleteByMap(map);
System.out.println(result);
}
4、邏輯刪除
- 物理刪除:真實刪除,將對應數據從數據庫中刪除,之後查詢不到此條被刪除數據
- 邏輯刪除:假刪除,將對應數據中代表是否被刪除字段狀態修改爲“被刪除狀態”,之後在數據庫中仍舊能看到此條數據記錄
(1)數據庫中添加 deleted字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean
(2)實體類添加deleted 字段
並加上 @TableLogic 註解 和 @TableField(fill = FieldFill.INSERT) 註解
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
(3)元對象處理器接口添加deleted的insert默認值
@Override
public void insertFill(MetaObject metaObject) {
......
this.setFieldValByName("deleted", 0, metaObject);
}
(4)application.properties 加入配置
此爲默認值,如果你的默認值和mp默認的一樣,該配置可無
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
(5)在 MybatisPlusConfig 中註冊 Bean
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
(6)測試邏輯刪除
- 測試後發現,數據並沒有被刪除,deleted字段的值由0變成了1
- 測試後分析打印的sql語句,是一條update
- 注意:被刪除數據的deleted 字段的值必須是 0,才能被選取出來執行邏輯刪除的操作
/**
* 測試 邏輯刪除
*/
@Test
public void testLogicDelete() {
int result = userMapper.deleteById(1L);
System.out.println(result);
}
(7)測試邏輯刪除後的查詢
MyBatis Plus中查詢操作也會自動添加邏輯刪除字段的判斷
/**
* 測試 邏輯刪除後的查詢:
* 不包括被邏輯刪除的記錄
*/
@Test
public void testLogicDeleteSelect() {
User user = new User();
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
測試後分析打印的sql語句,包含 WHERE deleted=0
SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0