一、创建springboot项目
引入pom文件依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<!--因为plus代码生成器需要一个模板引擎,velocity和freemarker任选一个,velocity是生成器中默认使用的,根据你的选择引依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
<!--mybatis-plus代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!--velocity模板-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
三、创建对应的mysql表
-- auto-generated definition
create table user
(
id int unsigned auto_increment
primary key,
name varchar(10) null,
pwd int(10) null,
gender int(10) null,
create_time datetime null,
update_time datetime null,
version int default 1 null,
deleted int default 0 null,
content json null
);
注意:数据库id字段一定要是自增!
四、编写mybaitsplus自动生成类,生成对应文件
public class Code {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=ture&characterEncoding=utf-8", "root", "123456")
.globalConfig(builder -> {
builder.outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
.author("fei")
.disableOpenDir()//不打开资源管理器
.dateType(DateType.TIME_PACK)
.commentDate("yyyy-MM-dd")//注释时间
.enableSwagger();
//.fileOverride();//覆盖已生成文件
}
)
.packageConfig(builder -> {
builder.parent("com.example.demo")
.moduleName("sys")
.entity("entity")
.service("service")
.serviceImpl("service.impl")
.mapper("mapper")
.xml("mapper")
.controller("controller")
.other("other")
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"));
}
)
.strategyConfig(Builder -> {
Builder.enableCapitalMode()
.enableSkipView()
.disableSqlFilter()
.addInclude("user")
.entityBuilder()
.enableLombok()
.enableTableFieldAnnotation()
.versionColumnName("version")
.versionPropertyName("version")//两种方式
.logicDeleteColumnName("deleted")
.logicDeletePropertyName("deleted")//两种方式
.naming(NamingStrategy.underline_to_camel)//表驼峰
.columnNaming(NamingStrategy.underline_to_camel)//列驼峰
.addTableFills(new Column("create_time", FieldFill.INSERT))
.addTableFills(new Property("updateTime", FieldFill.INSERT_UPDATE))//两种方式
.idType(IdType.AUTO)
.formatFileName("%sEntity")
.controllerBuilder()
.enableHyphenStyle()
.enableRestStyle()
.formatFileName("%sAction")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImp")
.mapperBuilder()
.superClass(BaseMapper.class)
.enableMapperAnnotation()
.enableBaseResultMap()
.enableBaseColumnList()
.formatMapperFileName("%sDao")
.formatXmlFileName("%sXml");
})
//.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
生成和自己添加的目录结构如图:
五、代码部分
- 配置类
package com.example.demo.sys.config;
import java.util.ArrayList;
/**
* @program: demos
* @description:
* @author: fei
* @create: 2021-11-21 12:21
*/
@Configuration
@EnableSwagger2
public class Myconfig {
//乐观锁
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
//配置了swagger的Docket的bean 实例
@Bean
public Docket docket0(Environment environment) {
// 设置Swagger显示环境
Profiles profiles = Profiles.of("dev", "test");
// 通过 environment.acceptsProfiles(profiles) 判断是否在自己设定的环境当中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("A")
.enable(flag)//不能在浏览器中访问swagger
.select()
// RequestHandlerSelectors 配置要扫描的包类
// basePackage(): 指定要扫描的包
// any(): 扫描全部
// none(): 都不扫描
// withClassAnnotation : 扫描类上的注解, 参数是一个注解的反射对象
// 例如:withClassAnnotation(RestController.class) 只扫描类上有@RestController注解的生成文档
// withMethodAnnotation: 扫描方法上的注解, 参数是一个注解的反射对象
.apis(RequestHandlerSelectors.any())
// paths(): 过滤路径
.paths(PathSelectors.ant("/sys/**"))//只扫描访问路径有sys的api
.build();
}
//配置了swagger的Docket 的 bean 实例
@Bean
public Docket docket(Environment environment) {
// 设置Swagger显示环境
Profiles profiles = Profiles.of("dev", "test");
// 通过 environment.acceptsProfiles(profiles) 判断是否在自己设定的环境当中
boolean flag = environment.acceptsProfiles(profiles);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("B")
.enable(flag)//不能在浏览器中访问swagger
.select()
.apis(RequestHandlerSelectors.any())
.build();
}
//配置 swagger 信息 = apiInfo
private ApiInfo apiInfo() {
//作者信息
Contact contact = new Contact("fei", "http://blog.fei.com/", "2495057802@qq.com");
return new ApiInfo("飞哥的SwaggerAPI文档",
"API文档",
"v1.0",
"http://blog.fei.com/",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList()
);
}
}
乐观锁:1.先查询获取版本号version=1,再更新。
–线程一 update user set name =“yi” ,version=version+1 where id=2 and version=1
–线程二 线程抢先完成,这个时候version=2,会导致线程一修改失败 update user set name =“yi” ,version=version+1 where id=2 and version=1
2.controller层
@RestController
@RequestMapping("/sys/user")
public class UserAction {
@Autowired
UserService userServiceImp;
@ResponseBody
@ApiOperation("test控制类")
@RequestMapping("/test")
public List<UserEntity> test() {
return userServiceImp.list();
}
}
注意:
name方式注入根据上面描述,注入userServiceImpl这个Bean时失败,
(失败的原因就是实现接口,而springboot的事务默认是使用jdk的动态代理,即基于接口))。
在action层中注入的Bean是实现类,因此就会报错。
- 实体类
@Data
public class ser {
private String id;
private String name;
private String nameEn;
private String avatar;
}
package com.example.demo.sys.entity;
/**
* <p>
*
* </p>
*
* @author fei
* @since 2021-11-21
*/
@Getter
@Setter
@TableName(value = "user", autoResultMap = true)
@ApiModel(value = "UserEntity对象", description = "你好")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField("name")
@ApiModelProperty("用户名")
private String name;
@TableField("pwd")
@ApiModelProperty("密码")
private Integer pwd;
@TableField(value = "gender", typeHandler = MyEnumTypeHanlder.class)
//typeHandler = MyEnumTypeHanlder.class 局部属性方式转换器注入mybatis
private GenderEnum gender;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField("version")
@Version
private Integer version;
@TableField("deleted")
@TableLogic
private Integer deleted;
@ApiModelProperty("联系方式")
@TableField(value = "content", typeHandler = FastjsonTypeHandler.class)
private List<ser> content;
@Override
public String toString() {
return "UserEntity{" +
"id=" + id +
", name='" + name + '\'' +
", pwd=" + pwd +
", gender=" + gender +
", createTime=" + createTime +
", updateTime=" + updateTime +
", version=" + version +
", deleted=" + deleted +
", content=" + content +
'}';
}
}
typeHandler = FastjsonTypeHandler.class MybatisPlus 自带的json类型转换器,不过需要引入json相关依赖,不然不起作用。
4.枚举类
public interface BaseEnum {
/**
* 根据枚举值和type获取枚举
*/
public static <T extends BaseEnum> T getEnum(Class<T> type, int value) {
T[] objs = type.getEnumConstants();
for (T em : objs) {
if (em.getValue().equals(value)) {
return em;
}
}
return null;
}
/**
* 获取枚举值
*
* @return
*/
Integer getValue();
/**
* 获取枚举文本
*
* @return
*/
String getLabel();
}
public enum GenderEnum implements BaseEnum {
MALE(0, "男"),
FEMALE(1, "女");
@EnumValue
private Integer value;
private String label;
GenderEnum(Integer value, String label) {
this.label = label;
this.value = value;
}
GenderEnum() {
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getLabel() {
return label;
}
}
5.填充策略代码
创建时间 . 修改时间! 这些个操作都是自动化完成的,我们不希望手动更新!
@Slf4j
@Component //把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("Start insert fill.... ");
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "deleted", Boolean.class, false);
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("Start update fill.... ");
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
5.mapper抽象类
@Mapper
@Repository
public interface UserDao extends BaseMapper<UserEntity> {
}
6.service层
public interface UserService extends IService<UserEntity> {
List<UserEntity> userlist();
}
@Service
public class UserServiceImp extends ServiceImpl<UserDao, UserEntity> implements UserService {
@Autowired
UserDao userDao;
@Override
public List<UserEntity> userlist() {
return userDao.selectList(null);
}
}
7.自定义枚举类型转换器
@MappedJdbcTypes(JdbcType.INTEGER)
@MappedTypes(GenderEnum.class)//限定作用范畴
public class MyEnumTypeHanlder extends BaseTypeHandler<GenderEnum> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, GenderEnum parameter, JdbcType jdbcType) throws SQLException {
// 枚举code对应的数据库字段类型
preparedStatement.setInt(i, parameter.getValue());
}
@Override
public GenderEnum getNullableResult(ResultSet resultSet, String columName) throws SQLException {
// 根据字段名获取枚举value值
int code = resultSet.getInt(columName);
// 获取枚举实体
GenderEnum instance = BaseEnum.getEnum(GenderEnum.class, code);
return instance;
}
@Override
public GenderEnum getNullableResult(ResultSet resultSet, int columIndex) throws SQLException {
int code = resultSet.getInt(columIndex);
GenderEnum instance = BaseEnum.getEnum(GenderEnum.class, code);
return instance;
}
@Override
public GenderEnum getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return null;
}
}
8.启动类
@EnableTransactionManagement
@MapperScan("com\\example\\demo\\sys\\mapper")
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
注意: @MapperScan(“com\example\demo\sys\mapper”)扫描mapper接口,经常因为没加报错。
9.application配置
# 应用名称
spring.application.name=demo
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=ture&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置逻辑删除
#删除之后deleted数据库字段改为1
mybatis-plus.global-config.db-config.logic-delete-value=1
#没删deleted数据库字段为0;
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus:
# type-handlers-package: com.example.demo.sys.typeHandler #包方式全局注入mybatis
mapper-locations: classpath:mapper/*Xml.xml # 根据项目工程更改
# type-aliases-package: com.example.entity #根据项目工程更改 别名
configuration:
cache-enabled: false #2级缓存
map-underscore-to-camel-case: true #开启驼峰
auto-mapping-behavior: full #全都自动映射
server:
port: 8080 #默认端口
spring:
profiles:
active: test #使用测试环境
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
spring:
profiles: test
自动映射属性设置 ,默认是PARTIAL,只会自动映射没有定义嵌套结果集映射的结果集,不会自动映射一对多的结果集需要写 ,属性名和字段名一样也要写属性名和字段名不一样,有自动映射也要写。
MybatisPlus官方文档
MybatisPlus还有许多好用的东西,大家可以试试。