集成springboot
依赖
- 核心依赖spring-boot-starter、lombo、mybatis-plus-boot-starter、mysql
- 使用Mybatis-plus代替Mybatis的依赖
<dependencies>
<!--核心 POM,包含自动配置支持、日志库和对 YAML 配置文件的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--核心 POM,包含自动配置支持、日志库和对 YAML 配置文件的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--支持使用 JDBC 访问数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- springboot的启动依赖(集成tomcat) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--Druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable{
Long id;
String author;
String Content;
String title;
Integer category_id;
Integer user_id;
Date create_time;
}
Mapper
- BaseMapper:泛型类,接受一个操作对象,实现该类的增删改查
@Repository
public interface ContentMapper extends BaseMapper<Content> {
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class ContentMapperTest {
@Resource
ContentMapper contentMapper;
@Test
public void list() throws Exception {
List<Content> list = contentMapper.selectList(null);
System.out.println("list = " + list);
}
}
条件查询
- orderByDesc: 排序
- isNotNull:不为空
- ge:匹配
- eq:大于
@Test
public void select() {
QueryWrapper<Content> wrapper = new QueryWrapper<>();
wrapper.eq("author", "Tom")
.isNotNull("title")
.orderByDesc("create_time"); // 排序
List<Content> contents = contentMapper.selectList(wrapper);
System.out.println("contents = " + contents);
}
修改自增策略
- 默认雪花算法设置id的值
- @TableId(type = IdType.AUTO):设置自增策略
- 自增策略包括:自增id(AUTO)、UUID、手动输入(INPUT)、空(NONE)..
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable{
@TableId(type = IdType.AUTO)
Long id;
String author;
String Content;
String title;
Integer category_id;
Integer user_id;
Date create_time;
}
自动填充
在插入或更新时,填充字段值
- @TableField(fill = FieldFill.INSERT):插入时填充
- @TableField(fill = FieldFill.INSERT_UPDATE):插入更新时填充
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable{
// 主键自增
@TableId(type = IdType.AUTO)
Long id;
String author;
String Content;
String title;
Integer category_id;
Integer user_id;
// 字段填充, 插入时填充
@TableField(fill = FieldFill.INSERT)
Date create_time;
// 插入和更新时填充
@TableField(fill = FieldFill.INSERT_UPDATE)
Date update_time;
}
实现自定义类
- 插入操作时调用insertFill方法,setFieldValByName设置属性值
// 插入时填充
@Override
public void insertFill(MetaObject metaObject) {
log.info("insertFill");
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
// 更新时填充
@Override
public void updateFill(MetaObject metaObject) {
log.info("updateFill");
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
测试
@Test
public void insert() {
Content content = new Content();
content.setAuthor("Tom");
content.setTitle("Everyone and Everything");
content.setContent("long long ago..");
// 返回受影响的行数
int insert = contentMapper.insert(content);
System.out.println("insert = " + insert);
}
乐观锁
乐观锁实现:当要更新一条记录的时候,希望这条记录没有被别人更新
- @Version:标记为一个乐观锁字段
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable{
// 主键自增
@TableId(type = IdType.AUTO)
Long id;
String author;
String Content;
String title;
Integer category_id;
Integer user_id;
// 乐观锁
@Version
Integer version;
// 字段填充, 插入时填充
@TableField(fill = FieldFill.INSERT)
Date create_time;
// 插入和更新时填充
@TableField(fill = FieldFill.INSERT_UPDATE)
Date update_time;
}
配置类配置乐观锁插件
/**
* mybatis plus 配置类
*/
@MapperScan("com.exp.dao")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfiguration {
/**
* 注册乐观锁和分页插件(新版:3.4.0)
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
// DbType:数据库类型(根据类型获取应使用的分页方言)
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 分页插件
return interceptor;
}
}
测试
@Test
public void lock() {
// 查询时获取version
Content content = contentMapper.selectById(126);
content.setAuthor("Mark");
// 更新时进行version比对,确定没有被人修改
contentMapper.updateById(content);
}
/**
*
* SELECT id,author,content,title,category_id AS category_id,user_id AS user_id,version,create_time AS create_time,update_time AS update_time FROM content WHERE id=?
*
* UPDATE content SET author=?, content=?, title=?, version=?, update_time=? WHERE id=? AND version=?
*
*/
测试更新操作被插队
- update操作会判断version是否被更改,没有则执行更新,并将version递增
@Test
public void lock() {
// 查询时获取version
Content content = contentMapper.selectById(126);
// 模拟更新操作被插队(可能时其他线程)
Content content1 = contentMapper.selectById(126);
content1.setAuthor("Link");
contentMapper.updateById(content1); // 此处已经将version更新
content.setAuthor("Nobita");
// 更新时进行version比对,确定没有被人修改,再更新version
contentMapper.updateById(content);
}
/**
*
* SELECT id,author,content,title,category_id AS category_id,user_id AS user_id,version,create_time AS create_time,update_time AS update_time FROM content WHERE id=?
*
* SELECT id,author,content,title,category_id AS category_id,user_id AS user_id,version,create_time AS create_time,update_time AS update_time FROM content WHERE id=?
*
* UPDATE content SET author=?, content=?, title=?, version=?, update_time=? WHERE id=? AND version=?
*
* UPDATE content SET author=?, content=?, title=?, version=?, update_time=? WHERE id=? AND version=?
*
*/
分页插件
配置类
@MapperScan("com.exp.dao")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfiguration {
/**
* 注册乐观锁和分页插件(新版:3.4.0)
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
// DbType:数据库类型(根据类型获取应使用的分页方言)
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 分页插件
return interceptor;
}
}
测试
- new Page<>(起始位置, 大小)
/**
* SELECT id,author,content,title,category_id AS category_id,user_id AS user_id,version,create_time AS create_time,update_time AS update_time FROM content LIMIT 0,1
*/
@Test
public void page() {
Page<Content> objectPage = new Page<>(1, 1);
IPage<Content> contentIPage = contentMapper.selectPage(objectPage, null);
contentIPage.getRecords().forEach(System.out::println);
System.out.println(contentIPage.getTotal()); // 获取总页数
System.out.println(contentIPage.getPages()); // 获取总数
System.out.println(contentIPage.getSize()); // 分页大小
System.out.println(contentIPage.getCurrent()); // 当前记录位置
}
逻辑删除
实体类逻辑字段
- @TableLogic:标记为一个逻辑字段
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content implements Serializable{
// 主键自增
@TableId(type = IdType.AUTO)
Long id;
String author;
String Content;
String title;
Integer category_id;
Integer user_id;
// 乐观锁
@Version
Integer version;
// 逻辑删除
@TableLogic
Integer deleted;
// 字段填充, 插入时填充
@TableField(fill = FieldFill.INSERT)
Date create_time;
// 插入和更新时填充
@TableField(fill = FieldFill.INSERT_UPDATE)
Date update_time;
}
配置文件
mybatis-plus:
configuration:
# 是否开启自动驼峰命名规则
map-underscore-to-camel-case: true
global-config:
db-config:
# 全局逻辑删除的实体字段名
logic-delete-field: flag
# 逻辑被删除时的值
logic-delete-value: 1
# 逻辑没有被删除的值
logic-not-delete-value: 0
mapper-locations: classpath:mapper/*.xml
测试
/**
* UPDATE content SET deleted=1 WHERE id=? AND deleted=0
*/
@Test
public void delete() {
contentMapper.deleteById(126L);
}
逆向工程
需要模板的依赖
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
/**
* 自动生成代码
*/
public class GeneratorCode {
public static void main(String[] args) {
// 生成器对象
AutoGenerator autoGenerator = new AutoGenerator();
// 配置策略
// 1.全局策略
GlobalConfig config = new GlobalConfig();
// 设置生成目录
String userDir = System.getProperty("user.dir"); // 获取工作目录
config.setOutputDir(userDir+"/src/main/java");
config.setAuthor("xiongyungang");
config.setFileOverride(false); // 覆盖原文件
config.setOpen(false); // 资源管理器中打开
config.setServiceName("%sService"); // 默认Service前缀I,使用正则去掉I前缀
config.setIdType(IdType.ID_WORKER); // 默认主键策略,雪花
autoGenerator.setGlobalConfig(config);
// 2.设置数据源
DataSourceConfig sourceConfig = new DataSourceConfig();
sourceConfig.setUrl("jdbc:mysql://localhost:3306/nobitan?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC");
sourceConfig.setDriverName("com.mysql.jdbc.Driver");
sourceConfig.setPassword("123456");
sourceConfig.setUsername("root");
sourceConfig.setDbType(DbType.MYSQL);
autoGenerator.setDataSource(sourceConfig);
// 3. 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setController("controller");
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
//packageConfig.setModuleName("nobitan");
packageConfig.setService("service");
packageConfig.setParent("top.xiongyungang");
autoGenerator.setPackageInfo(packageConfig);
// 4.策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("content"); // 设置的表名
strategyConfig.setEntityLombokModel(true); // 自动添加Lombok
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel); // _转驼峰
strategyConfig.setLogicDeleteFieldName("deleted"); // 逻辑删除
// 自动填充
TableFill createTimeFill = new TableFill("create_time", FieldFill.INSERT);
TableFill updateTimeFill = new TableFill("update_time", FieldFill.INSERT_UPDATE);
strategyConfig.setTableFillList(Arrays.asList(createTimeFill, updateTimeFill));
// 乐观锁
strategyConfig.setVersionFieldName("version");
strategyConfig.setRestControllerStyle(true);
strategyConfig.setControllerMappingHyphenStyle(true); // localhost/get_id_2
autoGenerator.setStrategy(strategyConfig);
// 执行生成器
autoGenerator.execute();
}
}