SpringBoot2 | 第七篇:整合BeetlSql

BeetSql 是一个全功能DAO工具, 同时具有 Hibernate 优点 & Mybatis 优点功能,适用于承认以SQL为中心,同时又需要工具能自动生成大量常用的SQL的应用。

[TOC]

BeetlSQL 特点

  • 开发效率
    • 无需注解,自动使用大量内置SQL,轻易完成增删改查功能,节省50%的开发工作量
    • 数据模型支持Pojo,也支持Map/List这种快速模型,也支持混合模型
    • SQL 模板基于Beetl实现,更容易写和调试,以及扩展
    • 可以针对单个表(或者视图)代码生成pojo类和sql模版,甚至是整个数据库。能减少代码编写工作量
  • 维护性
    • SQL 以更简洁的方式,Markdown方式集中管理,同时方便程序开发和数据库SQL调试。
    • 可以自动将sql文件映射为dao接口类
    • 灵活直观得支持一对一,一对多,多对多关系映射而不引入复杂的OR Mapping概念和技术。
    • 具备Interceptor功能,可以调试,性能诊断SQL,以及扩展其他功能
  • 其他
    • 内置支持主从数据库支持的开源工具
    • 性能数倍于JPA,MyBatis
    • 支持跨数据库平台,开发者所需工作减少到最小,目前跨数据库支持mysql,postgres,oracle,sqlserver,h2,sqllite,DB2.

环境/版本一览:

  • 开发工具:Intellij IDEA 2018.2.2
  • springboot: 2.0.5.RELEASE
  • jdk:1.8.0_171
  • maven:3.3.9
  • beetlsql:2.10.34

1、搭建

1538640158551

2、pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>

<!-- 引入beetl框架starter -->
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl-framework-starter</artifactId>
<version>1.1.63.RELEASE</version>
</dependency>
<!-- SpringBoot 热部署依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- 事务管理器依赖此包,tx 中带有 DaoSupport -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.8.RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- 导入 HikariCP 连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>

3、application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
datasource:
hikari:
# 基本属性
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/chapter7?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC&useSSL=false
username: root
password: 123456

#热部署的配置
devtools:
restart:
enabled: true

4、sql

创建数据库chapter7,并执行下面的sql

1
2
3
4
5
6
7
8
9
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) COLLATE utf8_bin DEFAULT NULL COMMENT '名称',
`password` VARCHAR(32) DEFAULT NULL COMMENT '密码',
`create_time` DATE DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

INSERT INTO `user` VALUES (1, 'fatal', '123456', '2018-10-21 11:52:41');

5、resources

resources 下面创建 sql 文件夹,在 sql 文件夹下,创建 user.md (该文件用来书写 sql 语句)

1
2
3
4
5
6
selectByName
===

* 一个简单的查询例子

select * from user where name = #name#

#表示占位符号,#name#表示将接收一个名称为 name 的参数

6、config

DataSourceConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.fatal.config;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
* 数据源配置类
*
* @author: Fatal
* @date: 2018/10/3 0003 21:49
*/
@Configuration
public class DataSourceConfig {

/**
* 配置数据库
* @desc @ConfigurationProperties 标注在方法上,会将配置数据映射到要`return`出来的对象中
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public DataSource dataSource() {
return new HikariDataSource();
}

}

BeetlSqlConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.fatal.config;

import org.beetl.sql.core.Interceptor;
import org.beetl.sql.core.UnderlinedNameConversion;
import org.beetl.sql.core.db.MySqlStyle;
import org.beetl.sql.ext.DebugInterceptor;
import org.beetl.sql.ext.spring4.BeetlSqlDataSource;
import org.beetl.sql.ext.spring4.BeetlSqlScannerConfigurer;
import org.beetl.sql.ext.spring4.SqlManagerFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
* BeetlSql配置类
* @author: Fatal
* @date: 2018/10/4 0004 13:01
*/
@Configuration
public class BeetlSqlConfig {

/**
* Mapper 接口扫描配置
*/
@Bean
public BeetlSqlScannerConfigurer beetlSqlScannerConfigurer() {
BeetlSqlScannerConfigurer conf = new BeetlSqlScannerConfigurer();
conf.setBasePackage("com.fatal.mapper");
conf.setDaoSuffix("Mapper");
conf.setSqlManagerFactoryBeanName("sqlManagerFactoryBean");
return conf;
}

@Bean
@Primary
public SqlManagerFactoryBean sqlManagerFactoryBean(@Qualifier("dataSource") DataSource datasource) {
SqlManagerFactoryBean factory = new SqlManagerFactoryBean();
BeetlSqlDataSource source = new BeetlSqlDataSource();
source.setMasterSource(datasource);
factory.setCs(source);
factory.setDbStyle(new MySqlStyle());
// 控制台或者日志系统输出执行的sql语句
factory.setInterceptors(new Interceptor[]{new DebugInterceptor()});
// 开启驼峰
factory.setNc(new UnderlinedNameConversion());
// sql文件路径
// factory.setSqlLoader(new ClasspathLoader("/sql")); // 默认就是放在 /resources/sql下
return factory;
}

}

7、entity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.fatal.entity;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
* @author: Fatal
* @date: 2018/10/3 0003 21:40
*/
@Data
@Accessors(chain = true)
public class User implements Serializable {

private Integer id;
private String name;
private String password;
private Date createTime;

}

8、mapper

Mapper 对应的sql文件默认根据实体来确定,如实体是UserInfo对象,则对应的sql文件是userInfo.md(sql)。可以通过@SqlResource 注解来指定Mapper对应的sql文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.fatal.mapper;

import com.fatal.entity.User;
import org.beetl.sql.core.annotatoin.SqlResource;
import org.beetl.sql.core.mapper.BaseMapper;

import java.util.List;

/**
* @author: Fatal
* @date: 2018/10/3 0003 21:47
*/
@SqlResource("user")
public interface IUserMapper extends BaseMapper<User> {

/**
* 根据name查找用户
* @param name 用户名
* @return
*/
List<User> selectByName(String name);

}

9、service

IUserService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.fatal.service;

import com.fatal.entity.User;

import java.util.List;

/**
* @author: Fatal
* @date: 2018/10/3 0003 21:54
*/
public interface IUserService {

User selectById(Integer id);

List<User> selectByName(String name);
}

IUserServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.fatal.service.impl;

import com.fatal.mapper.IUserMapper;
import com.fatal.entity.User;
import com.fatal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* @author: Fatal
* @date: 2018/10/3 0003 21:54
*/
@Service
public class UserServiceImpl implements IUserService {

@Autowired
private IUserMapper userMapper; // 这里会报红线,但不影响使用

@Override
public User selectById(Integer id) {
return userMapper.unique(id);
}

@Override
public List<User> selectByName(String name) {
return userMapper.selectByName(name);
}

}

10、controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.fatal.controller;

import com.fatal.entity.User;
import com.fatal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @author: Fatal
* @date: 2018/10/3 0003 21:56
*/
@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private IUserService userService;

/**
* 测试自带的查询功能
*/
@GetMapping("/{id}")
public User fatal(@PathVariable Integer id) {
User user = userService.getUserById(id);
return user;
}

/**
* 测试自定义sql
*/
@GetMapping("/query/{name}")
public List<User> fatal(@PathVariable String name) {
List<User> users = userService.select(name);
return users;
}

}

11、UserMapperTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.fatal.mapper;

import com.fatal.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

/**
* @author: Fatal
* @date: 2019/5/22 0022 16:17
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserMapperTest {

@Autowired
private IUserMapper userMapper;

@Test
public void lambdaQueryTest() {
List<User> users = userMapper.createLambdaQuery()
.andEq(User::getName, "fatal")
.andEq(User::getPassword, "123456")
.select();
System.out.println(users);
}

}

启动

1538642015162

测试

访问

1
http://localhost:8080/user/1

控制台

1538642254304

显示

1538642263243

访问

1
http://localhost:8080/user/query/fatal

控制台

1538642328125

显示

1538642335548

运行lambdaQueryTest(),控制台如下

1558514002571

整合成功啦!

参考资料

BeetlSQL2.10中文文档

Spring Boot教程第5篇:beatsql

总结

SpringBoot的知识已经有前辈在我们之前探索了。比较喜欢的博主有:唐亚峰 | Battcn方志朋的专栏程序猿DD纯洁的微笑。对这门技术感兴趣的可以去他们的博客逛逛。谢谢他们的分享~~

以上文章是我用来学习的Demo,都是基于 SpringBoot2.x 版本。

源码地址: https://github.com/ynfatal/springboot2-learning/tree/master/chapter7

学习 方志朋 前辈的经验