无需 XML Mapper,超级 Mybatis 代码即是 SQL 操作!真香?
阅读本文大概需要 8.5 分钟。
来自:JavaGuide
Fluent Mybatis 介绍 Fluent Mybatis 特性一览 Fluent Mybatis 原理 Fluent Mybatis vs Mybatis vs Mybatis Plus 实现需求比较 生成代码编码比较 三者对比总结 Fluent Mybatis 实战 引入依赖 创建表 创建数据库表对应的 Entity 类 配置数据源 测试 总结
Fluent Mybatis 介绍
Fluent Mybatis 特性一览
Fluent Mybatis 原理
Fluent Mybatis vs Mybatis vs Mybatis Plus
实现需求比较
create table `student_score`
(
id bigint auto_increment comment '主键ID' primary key,
student_id bigint not null comment '学号',
gender_man tinyint default 0 not null comment '性别, 0:女; 1:男',
school_term int null comment '学期',
subject varchar(30) null comment '学科',
score int null comment '成绩',
gmt_create datetime not null comment '记录创建时间',
gmt_modified datetime not null comment '记录最后修改时间',
is_deleted tinyint default 0 not null comment '逻辑删除标识'
) engine = InnoDB default charset=utf8;
select school_term,
subject,
count(score) as count,
min(score) as min_score,
max(score) as max_score,
avg(score) as max_score
from student_score
where school_term >= 2000
and subject in ('英语', '数学', '语文')
and score >= 60
and is_deleted = 0
group by school_term, subject
having count(score) > 1
order by school_term, subject;
复制代码
Mapper
接口public interface MyStudentScoreMapper {
List
SummaryQuery
@Data
@Accessors(chain = true)
public class SummaryQuery {
private Integer schoolTerm;
private Listsubjects;
private Integer score;
private Integer minCount;
}
复制代码
mapper xml
文件
复制代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = QuickStartApplication.class)
public class MybatisDemo {
@Autowired
private MyStudentScoreMapper mapper;
@Test
public void Mybatis_demo() {
// 构造查询参数
SummaryQuery paras = new SummaryQuery()
.setSchoolTerm(2000)
.setSubjects(Arrays.asList("英语", "数学", "语文"))
.setScore(60)
.setMinCount(1);
List
字段名称的记忆和敲码困难 Entity 属性跟随数据库字段发生变更后的运行时错误
生成代码编码比较
public class AppEntityGenerator {
static final String url = "jdbc:mysql://localhost:3306/fluent_Mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
public static void main(String[] args) {
FileGenerator.build(Abc.class);
}
@Tables(
/** 数据库连接信息 **/
url = url, username = "root", password = "password",
/** Entity类parent package路径 **/
basePack = "cn.org.fluent.Mybatis.springboot.demo",
/** Entity代码源目录 **/
srcDir = "spring-boot-demo/src/main/java",
/** Dao代码源目录 **/
daoDir = "spring-boot-demo/src/main/java",
/** 如果表定义记录创建,记录修改,逻辑删除字段 **/
gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted",
/** 需要生成文件的表 ( 表名称:对应的Entity名称 ) **/
tables = @Table(value = {"student_score"})
)
static class Abc {
}
}
public class CodeGenerator {
static String dbUrl = "jdbc:mysql://localhost:3306/fluent_Mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
@Test
public void generateCode() {
GlobalConfig config = new GlobalConfig();
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL)
.setUrl(dbUrl)
.setUsername("root")
.setPassword("password")
.setDriverName(Driver.class.getName());
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig
.setCapitalMode(true)
.setEntityLombokModel(false)
.setNaming(NamingStrategy.underline_to_camel)
.setColumnNaming(NamingStrategy.underline_to_camel)
.setEntityTableFieldAnnotationEnable(true)
.setFieldPrefix(new String[]{"test_"})
.setInclude(new String[]{"student_score"})
.setLogicDeleteFieldName("is_deleted")
.setTableFillList(Arrays.asList(
new TableFill("gmt_create", FieldFill.INSERT),
new TableFill("gmt_modified", FieldFill.INSERT_UPDATE)));
config
.setActiveRecord(false)
.setIdType(IdType.AUTO)
.setOutputDir(System.getProperty("user.dir") + "/src/main/java/")
.setFileOverride(true);
new AutoGenerator().setGlobalConfig(config)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(
new PackageConfig()
.setParent("com.mp.demo")
.setController("controller")
.setEntity("entity")
).execute();
}
}
三者对比总结
Fluent Mybatis 实战
引入依赖
com.github.atool
fluent-mybatis
1.9.3
com.github.atool
fluent-mybatis-processor
1.9.3
创建表
create schema fluent_mybatis;
create table hello_world
(
id bigint unsigned auto_increment primary key,
say_hello varchar(100) null,
your_name varchar(100) null,
gmt_created datetime DEFAULT NULL COMMENT '创建时间',
gmt_modified datetime DEFAULT NULL COMMENT '更新时间',
is_deleted tinyint(2) DEFAULT 0 COMMENT '是否逻辑删除'
) ENGINE = InnoDB
CHARACTER SET = utf8 comment '简单演示表';
创建数据库表对应的 Entity 类
Entity
类: HelloWorldEntity
, 你只需要简单的做 3 个动作:根据驼峰命名规则命名 Entity
类和字段HelloWorldEntity
继承IEntity
接口类在 HelloWorldEntity
类上加注解@FluentMybatis
@FluentMybatis
public class HelloWorldEntity extends RichEntity {
private Long id;
private String sayHello;
private String yourName;
private Date gmtCreated;
private Date gmtModified;
private Boolean isDeleted;
// get, set, toString 方法
@Override
public Class extends IEntity> entityClass() {
return HelloWorldEntity.class;
}
}
mvn clean compile
gradle clean compile
配置数据源
数据源 DataSource 配置 Mybatis 的 mapper 扫描路径 Mybatis 的 SqlSessionFactoryBean
@ComponentScan(basePackages = "cn.org.atool.fluent.mybatis.demo1")
@MapperScan("cn.org.atool.fluent.mybatis.demo1.entity.mapper")
@Configuration
public class HelloWorldConfig {
/**
* 设置dataSource属性
*
* @return
*/
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/fluent_mybatis?useUnicode=true&characterEncoding=utf8");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
/**
* 定义mybatis的SqlSessionFactoryBean
*
* @param dataSource
* @return
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean;
}
@Bean
public MapperFactory mapperFactory() {
return new MapperFactory();
}
}
测试
HelloWorldEntity
对应的 Mapper
类: HelloWorldMapper
, 这个类是 Fluent Mybatis 编译时生成的。HelloWorldMapper
进行删除、插入、查询、修改操作。@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = HelloWorldConfig.class)
public class HelloWorldTest {
/**
* Fluent Mybatis编译时生成的Mapper类
*/
@Autowired
HelloWorldMapper mapper;
@Test
public void testHelloWorld() {
/**
* 为了演示方便,先删除数据
*/
mapper.delete(mapper.query()
.where.id().eq(1L).end());
/**
* 插入数据
*/
HelloWorldEntity entity = new HelloWorldEntity();
entity.setId(1L);
entity.setSayHello("hello world");
entity.setYourName("Fluent Mybatis");
entity.setIsDeleted(false);
mapper.insert(entity);
/**
* 查询 id = 1 的数据
*/
HelloWorldEntity result1 = mapper.findOne(mapper.query()
.where.id().eq(1L).end());
/**
* 控制台直接打印出查询结果
*/
System.out.println("1. HelloWorldEntity:" + result1.toString());
/**
* 更新id = 1的记录
*/
mapper.updateBy(mapper.updater()
.set.sayHello().is("say hello, say hello!")
.set.yourName().is("Fluent Mybatis is powerful!").end()
.where.id().eq(1L).end()
);
/**
* 查询 id = 1 的数据
*/
HelloWorldEntity result2 = mapper.findOne(mapper.query()
.where.sayHello().like("hello")
.and.isDeleted().eq(false).end()
.limit(1)
);
/**
* 控制台直接打印出查询结果
*/
System.out.println("2. HelloWorldEntity:" + result2.toString());
}
}
1. HelloWorldEntity:HelloWorldEntity{id=1, sayHello='hello world', yourName='Fluent Mybatis', gmtCreate=null, gmtModified=null, isDeleted=false}
2. HelloWorldEntity:HelloWorldEntity{id=1, sayHello='say hello, say hello!', yourName='Fluent Mybatis is powerful!', gmtCreate=null, gmtModified=null, isDeleted=false}
Entity
类上 @FluentMybatis
注解在编译时, 会在 target 目录 class 目录下自动编译生成一系列文件:mapper/*Mapper
: Mybatis 的Mapper
定义接口, 定义了一系列通用的数据操作接口方法。dao/*BaseDao
:Dao
实现基类, 所有的DaoImpl
都继承各自基类 根据分层编码的原则,我们不会在Service
类中直接使用Mapper
类,而是引用Dao
类。我们在Dao
实现类中根据条件实现具体的数据操作方法。wrapper/*Query
: Fluent Mybatis 核心类, 用来进行动态 sql 的构造, 进行条件查询。wrapper/*Updater
: Fluent Mybatis 核心类, 用来动态构造update
语句。helper/*Mapping
:Entity
表字段和Entity
属性映射定义类helper/*Segment
:Query
和Updater
具体功能实现, 包含几个实现:select
,where
,group by
,having by
,order by
,limit
IEntityRelation
: 处理Entity
关联(一对一, 一对多, 多对多)关系的接口Ref
: 引用 Fluent Mybatis 生成的对象的快捷入口工具类
总结
推荐阅读:
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级......等技术栈!
⬇戳阅读原文领取! 朕已阅