主鍵政策
Mybatis-Plus提供了一個注解@TableId, 該注解提供了各種的主鍵生成政策。
package com.demo;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class PrimaryKeyTest {
@Autowired
private UserMapper userMapper;
}
- AUTO:跟随資料庫表的主鍵遞增政策,前提資料庫表的主鍵設定為自增
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
@Test
void primary() {
User user = new User();
user.setName("Mary");
user.setAge(35);
user.setEmail("[email protected]");
userMapper.insert(user);
}
- INPUT:手動插入id,否則無法添加資料
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.INPUT)
private Long id;
private String name;
private Integer age;
private String email;
}
package com.demo;
import com.demo.domain.User;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class PrimaryKeyTest {
@Autowired
private UserMapper userMapper;
@Test
void primary() {
User user = new User();
// 手動設定ID
user.setId(7L);
user.setName("Mary");
user.setAge(35);
user.setEmail("[email protected]");
userMapper.insert(user);
}
}
- ASSIGN_ID
資料量很大,要進行分表:
1)水準拆分:按照資料量進行拆分
2)垂直拆分:按照字段進行拆分
- 雪花算法:解決主鍵自增問題而生的
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.ASSIGN_ID) // ASSIGN_ID 雪花算法
private Long id;
private String name;
private Integer age;
private String email;
}
// 插入的id是19位長度的十進制數,其實就是64位二進制得到的結果
@Test
void primary() {
User user = new User();
user.setName("Mary");
user.setAge(35);
user.setEmail("[email protected]");
userMapper.insert(user);
}
- NONE:不指定主鍵生成政策,跟随的是全局政策
mybatis-plus:
global-config:
db-config:
id-type: ASSIGN_ID # 全局政策的預設值
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.NONE) // 與不設定@TableId是一樣的,都使用的是全局政策
private Long id;
private String name;
private Integer age;
private String email;
}
// 插入的id是19位長度的十進制數,其實就是64位二進制得到的結果
@Test
void primary() {
User user = new User();
user.setName("Mary");
user.setAge(35);
user.setEmail("[email protected]");
userMapper.insert(user);
}
- ASSIGN_UUID
UUID(Universally Unique Identifier)全局唯一辨別符,定義為一個字元串主鍵,采用32位數字組成。
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String name;
private Integer age;
private String email;
}
@Test
void primary() {
User user = new User();
user.setName("Mary");
user.setAge(35);
user.setEmail("[email protected]");
userMapper.insert(user);
}
id由bigint改為varchar(50)
分頁
分頁的本質就是需要設定一個攔截器,通過攔截器攔截SQL,通過在SQL語句的結尾添加limit關鍵字,來實作分頁的效果。
- 分頁插件
package com.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 分頁插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
package com.demo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.domain.User;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class PageTest {
@Autowired
private UserMapper userMapper;
@Test
void selectPage() {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 指定分頁對象
IPage<User> userPage = new Page<>(1, 3);
// 執行查詢
userMapper.selectPage(userPage, lambdaQueryWrapper);
// 擷取分頁查詢的資訊
System.out.println("目前頁:" + userPage.getCurrent());
System.out.println("每頁顯示條數:" + userPage.getSize());
System.out.println("總頁數:" + userPage.getPages());
System.out.println("總條數:" + userPage.getTotal());
System.out.println("分頁資料:" + userPage.getRecords());
}
}
- 自定義分頁插件
package com.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.demo.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
IPage<User> selectByName(IPage<User> page, String name);
}
package com.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.demo.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
IPage<User> selectByName(IPage<User> page, String name);
}
package com.demo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.domain.User;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class PageTest {
@Autowired
private UserMapper userMapper;
@Test
void selectPage() {
// 指定分頁對象
IPage<User> userPage = new Page<>(1, 2);
// 執行查詢
userMapper.selectByName(userPage, "Mary");
// 擷取分頁查詢的資訊
System.out.println("目前頁:" + userPage.getCurrent());
System.out.println("每頁顯示條數:" + userPage.getSize());
System.out.println("總頁數:" + userPage.getPages());
System.out.println("總條數:" + userPage.getTotal());
System.out.println("分頁資料:" + userPage.getRecords());
}
}
ActiveRecord模式
ActiveRecord(活動記錄)是一種領域模型模式,特點是一個模型類對應關系型資料庫中的一個表,而模型類的一個執行個體對應表中的一行記錄,圍繞一個資料對象進行CRUD操作,需要讓實體類繼承Model類且實作主鍵指定方法。
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Model<User> {
@TableId
private Long id;
private String name;
private Integer age;
private String email;
}
package com.demo;
import com.demo.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ActiveRecordTest {
// 添加
@Test
void activeRecordAdd() {
User user = new User();
user.setName("zhang");
user.setAge(30);
user.setEmail("[email protected]");
user.insert();
}
// 删除
@Test
void activeRecordDelete() {
User user = new User();
user.setId(1653291729962430466L);
user.deleteById();
}
// 修改
@Test
void activeRecordUpdate() {
User user = new User();
user.setId(7L);
user.setAge(50);
user.updateById();
}
// 查詢
@Test
void activeRecordSelect() {
User user = new User();
user.setId(7L);
User result = user.selectById();
System.out.println("result = " + result);
}
}
SimpleQuery工具類
package com.demo.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- list: 基于字段封裝集合
package com.demo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery;
import com.demo.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class SimpleQueryTest {
@Test
void testList() {
List<Long> idList = SimpleQuery.list(new LambdaQueryWrapper<User>().eq(User::getName, "Mary"), User::getId);
System.out.println("idList = " + idList);
}
}
package com.demo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery;
import com.demo.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.swing.text.html.Option;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@SpringBootTest
public class SimpleQueryTest {
@Test
void testList() {
List<String> nameList = SimpleQuery.list(new LambdaQueryWrapper<User>().eq(User::getName, "Mary"), User::getName, new Consumer<User>() {
@Override
public void accept(User user) {
Optional.of(user.getName()).map(String::toLowerCase).ifPresent(user::setName);
}
});
System.out.println("nameList = " + nameList);
}
}
- map
// 将所有元素封裝為Map
@Test
void testMap() {
Map<Long, User> longUserMap = SimpleQuery.keyMap(new LambdaQueryWrapper<User>(), User::getId);
System.out.println("longUserMap = " + longUserMap);
}
// 一條元素封裝為Map
@Test
void testMap() {
Map<Long, User> longUserMap = SimpleQuery.keyMap(new LambdaQueryWrapper<User>().eq(User::getId, 1L), User::getId);
System.out.println("longUserMap = " + longUserMap);
}
// 任意元素字段封裝為Map
@Test
void testMap() {
Map<Long, String> map = SimpleQuery.map(new LambdaQueryWrapper<User>(), User::getId, User::getName);
System.out.println("map = " + map);
}
- Group
@Test
void testGroup() {
Map<String, List<User>> map = SimpleQuery.group(new LambdaQueryWrapper<User>(), User::getName);
System.out.println("map = " + map);
}
邏輯删除
不是真的删除,增加一個字段來表示這個資料的狀态,實際上是更新資料的狀态。
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
// 增加一個狀态字段
@TableLogic(value = "1", delval = "0")
private Integer status;
}
package com.demo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.demo.domain.User;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class LogicTest {
@Autowired
private UserMapper userMapper;
@Test
void logicDelete() {
userMapper.deleteById(7L);
}
// 邏輯删除的資料,是查詢不出來的,除非status=0的條件才能查詢出資料
@Test
void logicSelect() {
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getId, 7L);
User user = userMapper.selectOne(lambdaQueryWrapper);
System.out.println("user = " + user);
}
}
[愛慕]全局配置邏輯删除
mybatis-plus:
global-config:
db-config:
logic-delete-field: status
logic-delete-value: 0
logic-not-delete-value: 1
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
// 增加一個狀态字段
// @TableLogic(value = "1", delval = "0")
private Integer status;
}
通用枚舉
表示一組資訊,這組資訊隻能從一些固定的值中進行選擇,不能随意寫,這種場景下,枚舉最合适。
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.demo.enums.GenderEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer status;
private GenderEnum gender;
}
package com.demo.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
public enum GenderEnum {
MAN(0, "男"),WOMAN(1, "女");
// @EnumValue 解決資料庫的類型和枚舉類型沒辦法轉換,報錯的問題
@EnumValue
private Integer gender;
private String genderName;
GenderEnum(Integer gender, String genderName) {
this.gender = gender;
this.genderName = genderName;
}
}
package com.demo;
import com.demo.domain.User;
import com.demo.enums.GenderEnum;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class EnumTest {
@Autowired
private UserMapper userMapper;
@Test
void enumTest() {
User user = new User();
user.setName("liu");
user.setAge(29);
user.setEmail("[email protected]");
user.setStatus(1);
user.setGender(GenderEnum.MAN);
userMapper.insert(user);
}
}
字段類型處理器
實體類的Map類型和資料庫的varchar類型的互相轉換,需要字段類型處理器來完成。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.demo.enums.GenderEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(autoResultMap = true)
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer status;
private GenderEnum gender;
@TableField(typeHandler = FastjsonTypeHandler.class)
private Map<String, String> contact; // 聯系方式
}
@Test
void typeHandler() {
User user = new User();
user.setName("li");
user.setAge(28);
user.setEmail("[email protected]");
user.setGender(GenderEnum.MAN);
user.setStatus(1);
HashMap<String, String> map = new HashMap<>();
map.put("tel", "13888888999");
map.put("phone", "010-12345678");
user.setContact(map);
userMapper.insert(user);
}
@Test
void typeHandlerSelect() {
List<User> users = userMapper.selectList(null);
System.out.println("users = " + users);
}
自動填充功能
建立時間和更新時間可以設定為自動填充。
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 隻有設定了下劃線和小駝峰映射,才能和實體類完成映射
設定MySQL的時區
-- 中國時區 東八區
set GLOBAL time_zone = '+8:00'
目前工程環境的時區
url: jdbc:mysql://localhost:3306/mq?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.demo.enums.GenderEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(autoResultMap = true)
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer status;
private GenderEnum gender;
@TableField(typeHandler = FastjsonTypeHandler.class)
private Map<String, String> contact; // 聯系方式
// 設定時間,還要考慮時區因素(資料庫本身和目前工程環境的時區)
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
package com.demo.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
setFieldValByName("createTime", new Date(), metaObject);
setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
setFieldValByName("updateTime", new Date(), metaObject);
}
}
package com.demo;
import com.demo.domain.User;
import com.demo.enums.GenderEnum;
import com.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
@SpringBootTest
public class FillTest {
@Autowired
private UserMapper userMapper;
@Test
void testFillInsert() {
User user = new User();
user.setName("wang");
user.setAge(35);
user.setEmail("[email protected]");
user.setGender(GenderEnum.MAN);
user.setStatus(1);
HashMap<String, String> map = new HashMap<>();
map.put("tel", "13888888999");
map.put("phone", "010-12345678");
user.setContact(map);
userMapper.insert(user);
}
@Test
void testFillUpdate() {
// 1653386151156793346
User user = new User();
user.setId(1653386151156793346L);
user.setName("wangwu");
user.setAge(39);
user.setEmail("[email protected]");
user.setGender(GenderEnum.MAN);
user.setStatus(1);
HashMap<String, String> map = new HashMap<>();
map.put("tel", "13888888999");
map.put("phone", "010-12345678");
user.setContact(map);
userMapper.updateById(user);
}
}
防全表更新與删除插件
package com.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 分頁插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 防全表更新與删除插件
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
MybatisX逆向工程
MybatisX快速代碼生成
package com.demo.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.demo.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
int deleteByNameAndAge(@Param("name") String name, @Param("age") Integer age);
int updateNameByAge(@Param("name") String name, @Param("age") Integer age);
List<User> selectAllByAgeBetween(@Param("beginAge") Integer beginAge, @Param("endAge") Integer endAge);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.demo.domain.User">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="age" column="age" jdbcType="INTEGER"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="INTEGER"/>
<result property="gender" column="gender" jdbcType="INTEGER"/>
<result property="contact" column="contact" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,name,age,
email,status,gender,
contact,create_time,update_time
</sql>
<delete id="deleteByNameAndAge">
delete
from user
where name = #{name,jdbcType=VARCHAR}
AND age = #{age,jdbcType=NUMERIC}
</delete>
<update id="updateNameByAge">
update user
set name = #{name,jdbcType=VARCHAR}
where age = #{age,jdbcType=NUMERIC}
</update>
<select id="selectAllByAgeBetween" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where
age between #{beginAge,jdbcType=INTEGER} and #{endAge,jdbcType=INTEGER}
</select>
</mapper>
并發問題
多個使用者修改同一個資料時,要求隻有一個請求修改資料,其它的不允許修改。
- 悲觀鎖
- 樂觀鎖
1)在資料庫表中添加一個字段version,表示版本,預設值是1;
2)找到實體類,添加對應的屬性,并使用@version表諸位這是一個樂觀鎖字段資訊。
package com.demo.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import com.demo.enums.GenderEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(autoResultMap = true)
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private Integer status;
private GenderEnum gender;
@TableField(typeHandler = FastjsonTypeHandler.class)
private Map<String, String> contact; // 聯系方式
// 設定時間,還要考慮時區因素(資料庫本身和目前工程環境的時區)
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
@Version // 樂觀鎖
private Integer version;
}
package com.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 分頁插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 實作樂觀鎖的控制
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
代碼生成器
<!--代碼生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>
<!--freemarker模闆依賴-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
FastAutoGenerator.create("url", "username", "password")
.globalConfig(builder -> {
builder.author("baomidou") // 設定作者
.enableSwagger() // 開啟 swagger 模式
.fileOverride() // 覆寫已生成檔案
.outputDir("D://"); // 指定輸出目錄
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定義類型轉換
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.parent("com.baomidou.mybatisplus.samples.generator") // 設定父包名
.moduleName("system") // 設定父包子產品名
.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 設定mapperXml生成路徑
})
.strategyConfig(builder -> {
builder.addInclude("t_simple") // 設定需要生成的表名
.addTablePrefix("t_", "c_"); // 設定過濾表字首
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模闆,預設的是Velocity引擎模闆
.execute();
執行SQL分析列印
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
spring:
datasource:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://localhost:3306/mq?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
username: root
password: root
# ***spy.properties***
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定義日志列印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志輸出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系統記錄 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 設定 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL字首
useprefix=true
# 配置記錄 Log 例外,可去掉的結果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 實際驅動可多個
#driverlist=org.h2.Driver
# 是否開啟慢SQL記錄
outagedetection=true
# 慢SQL記錄标準 2 秒
outagedetectioninterval=2
多資料源環境
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
spring:
datasource:
dynamic:
primary: master
strict: false
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mq?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
username: root
password: root
slave_1:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mq1?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
username: root
password: root