dtt-spring-boot-parent
dtt-spring-boot-parent copied to clipboard
DTT is an object-oriented Java framework that enables developers to automatically create database tables based on domain models through annotation-driven development, increasing productivity for devel...
dtt-spring-boot-starter
- What is DTT?
It's means
domain-to-table, aims to make it easy for you to automatically create DB tables based on your Java domain object model, domain driven table is the concept ofDTT;
- What can DTT do?
Tips: Read about DDT's features to learn more.
(a) Converts your Java domain object to
RDBtableDDLstatements and auto create them.(b) Supports the ability for
mybatisto create table lazily on demand just likehibernateandspring-data-jpacan do.(c) Exports an
all-in-oneDDL statements for all tables as local file.(d) Retains comments for columns of data tables for the Java developers who is non-native English speaker.
here is an example for the
0-codeinjection way to parse Java document to a table DDL statements.
- Chinese developer
- Java domian
import com.example.enums.MemberType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; /** * ç¨æ·ä¿¡æ¯ */ @Data @Builder @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) public class DttMember implements Serializable { private static final long serialVersionUID = 1L; /** * 主é®id */ private Long id; /** * ç¨æ·openId */ private String openId; /** * ç¨æ·æµç§° */ private String nickname; /** * æ¯å¦å¯ç¨, é»è®¤ï¼1 */ private Boolean isEnable = true; /** * ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00 */ private BigDecimal balance = BigDecimal.valueOf(0L, 2); /** * åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss */ private LocalDateTime birthday; /** * ä¼åç±»åï¼é»è®¤ï¼ORDINARY */ private MemberType memberType = MemberType.ORDINARY; /** * ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸ */ private Integer status = 3; /** * è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷 */ private Integer deleted = 0; /** * æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd */ private LocalDate registrarDate; /** * ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss */ private LocalTime accelerateBeginTime; /** * ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss */ private LocalTime accelerateEndTime; /** * ä¿®æ¹æ¶é´ */ private LocalDateTime updateTime; }
- Table statements
DROP TABLE IF EXISTS `db_demo`.`dtt_member`; CREATE TABLE IF NOT EXISTS `db_demo`.`dtt_member` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®id', `status` int DEFAULT 3 COMMENT 'ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸', `deleted` int DEFAULT 0 COMMENT 'è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷', `open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç¨æ·openId', `balance` decimal DEFAULT 0.00 COMMENT 'ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00', `accelerate_begin_time` time DEFAULT NULL COMMENT 'ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss', `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç¨æ·æµç§°', `birthday` datetime DEFAULT NULL COMMENT 'åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss', `member_type` enum ('ORDINARY','STUDENT','GUNMETAL','SILVER','GOLD','DIAMOND','SPORTS','PLUS') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'ORDINARY' COMMENT 'ä¼åç±»åï¼é»è®¤ï¼ORDINARY', `is_enable` tinyint DEFAULT true COMMENT 'æ¯å¦å¯ç¨, é»è®¤ï¼1', `registrar_date` date DEFAULT NULL COMMENT 'æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd', `accelerate_end_time` time DEFAULT NULL COMMENT 'ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss', `update_time` datetime DEFAULT NULL COMMENT 'ä¿®æ¹æ¶é´', PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT ='ç¨æ·ä¿¡æ¯';
- As you can seeï¼In your DB:
- Korean developer
- Java domain
import com.example.enums.MemberType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; /** * ì¬ì©ì ì ë³´ */ @Data @Builder @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) public class DttMember implements Serializable { private static final long serialVersionUID = 1L; /** * 기본 í¤ ID */ private Long id; /** * ì¬ì©ì openId */ private String openId; /** * ì¬ì©ì ëë¤ì ì¬ì©ì ëë¤ì */ private String nickname; /** * íì±í ì¬ë¶, 기본ê°: 1 */ private Boolean isEnable = true; /** * ì¬ì©ì ì ì© ìì¡, 기본ê°: 0.00 */ private BigDecimal balance = BigDecimal.valueOf(0L, 2); /** * ìë ìì¼, íì: yyyy-MM-dd HH:mm:ss */ private LocalDateTime birthday; /** * íì ì í, 기본ê°: ORDINARY */ private MemberType memberType = MemberType.ORDINARY; /** * ì¬ì©ì ìí: 0 ì ì(기본ê°), 1 ëê²°, 2 ê³ì ì°¨ë¨, 3 ê³ì ë¹ì ì */ private Integer status = 3; /** * ê³ì ì·¨ì ìí, 0ì ì·¨ìëì§ ìì(기본ê°), 1ì ì·¨ìë¨ */ private Integer deleted = 0; /** * ë±ë¡ ìê°, íì: yyyy-MM-dd */ private LocalDate registrarDate; /** * íì ê°ì ìì ìê°, íì: HH:mm:ss */ private LocalTime accelerateBeginTime; /** * íì ê°ì ì¢ ë£ ìê°, íì: HH:mm:ss */ private LocalTime accelerateEndTime; /** * ìê° ë³ê²½ */ private LocalDateTime updateTime; }
- DB table
DROP TABLE IF EXISTS `db_demo`.`dtt_member`; CREATE TABLE IF NOT EXISTS `db_demo`.`dtt_member` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '기본 í¤ ID', `status` int DEFAULT 3 COMMENT 'ì¬ì©ì ìí: 0 ì ì(기본ê°), 1 ëê²°, 2 ê³ì ì°¨ë¨, 3 ê³ì ë¹ì ì', `is_enable` tinyint DEFAULT true COMMENT 'íì±í ì¬ë¶, 기본ê°: 1', `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ì¬ì©ì ëë¤ì ì¬ì©ì ëë¤ì', `birthday` datetime DEFAULT NULL COMMENT 'ìë ìì¼, íì: yyyy-MM-dd HH:mm:ss', `member_type` enum('ORDINARY','STUDENT','GUNMETAL','SILVER','GOLD','DIAMOND','SPORTS','PLUS') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'ORDINARY' COMMENT 'íì ì í, 기본ê°: ORDINARY', `registrar_date` date DEFAULT NULL COMMENT 'ë±ë¡ ìê°, íì: yyyy-MM-dd', `accelerate_begin_time` time DEFAULT NULL COMMENT 'íì ê°ì ìì ìê°, íì: HH:mm:ss', `accelerate_end_time` time DEFAULT NULL COMMENT 'íì ê°ì ì¢ ë£ ìê°, íì: HH:mm:ss', `update_time` datetime DEFAULT NULL COMMENT 'ìê° ë³ê²½', `deleted` int DEFAULT 0 COMMENT 'ê³ì ì·¨ì ìí, 0ì ì·¨ìëì§ ìì(기본ê°), 1ì ì·¨ìë¨', `open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ì¬ì©ì openId', `balance` decimal DEFAULT 0.00 COMMENT 'ì¬ì©ì ì ì© ìì¡, 기본ê°: 0.00', PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT ='ì¬ì©ì ì ë³´';You can easily use DTT integrate with spring's ecosystem(mybatis-plus, mybatis, ... ) and enhance themï¼For mybatis-plus you integrate with
0-Code.
Architecture

Quick Start
- Add maven dependencies to your
pom.xml
<dependencies>
<!-- dtt-spring-boot-starter -->
<dependency>
<groupId>io.github.weasley-j</groupId>
<artifactId>dtt-spring-boot-starter</artifactId>
<version>1.3.5</version>
</dependency>
<!-- javadoc-scribe start -->
<dependency>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
<version>0.15.0</version>
<scope>provided</scope>
</dependency>
<!-- javadoc-scribe end -->
</dependencies>
OR
- Clone this project into your dir.
git clone https://github.com/Weasley-J/dtt-spring-boot-parent.git
- CD to your work dir then you can run this maven command to install DTT and use it in you projects.
Tips: For this step, I mean your JDK and MAVEN environment are set correctly.
mvn clean install -pl :dtt-spring-boot-starter -am
- Add maven dependencies into your
pom.xml(The pom's parent must be extendsorg.springframework.boot:spring-boot-starter-parent)
Tips: domain model must be in the same src folder with pom.xml
<dependencies>
<!-- dtt-spring-boot-starter -->
<dependency>
<groupId>io.github.weasley-j</groupId>
<artifactId>dtt-spring-boot-starter</artifactId>
<version>1.3.5</version>
</dependency>
<!-- javadoc-scribe start -->
<dependency>
<groupId>com.github.therapi</groupId>
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
<version>0.15.0</version>
<scope>provided</scope>
</dependency>
<!-- javadoc-scribe end -->
</dependencies>
- Config your projects datasource in
application.yml, like this:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://your_ip:3306/your_db?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true&allowMultiQueries=true
username: your_username
password: your_password
- Using JAVA annotation
@EnableDttto enable DTT to your projects Main class, As follow:
import cn.alphahub.dtt.plus.enums.ParserType;
import cn.alphahub.dtt.plus.framework.annotations.EnableDtt;
import com.example.domain.dtt.DttMember;
import com.example.domain.dtt.DttPerson;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* MyDtt-Plus Testing Application
*/
@SpringBootApplication
@EnableDtt(
scanBasePackages = {
"com.example.i18n.korean",
"com.example.domain.dtt",
"com.example.domain.oms", "com.example.domain.order", "com.example.domain.payment",
"com.example.domain.promotion", "com.example.domain.shop", "com.example.domain.user",
},
parserType = ParserType.JAVA_DOC,
dropTableBeforeCreate = true,
scanBaseClasses = {
DttPerson.class,
DttMember.class,
}
)
@MapperScan(basePackages = {"com.example.mapper"})
public class MydttPlusTestsApplication {
public static void main(String[] args) {
SpringApplication.run(MydttPlusTestsApplication.class, args);
}
}
You can enable the required functions as needed. When your application started. You'll be see like this console log in your IDE:
2022-07-17 22:15:13.894 INFO 12961 --- [ main] c.a.dtt.plus.framework.InitDttHandler : Auto created '1' tables for '0' seconds. detail: {"dttStartTime":"2022-07-17 22:15:13","dttEndTime":"2022-07-17 22:15:13"}, location: /Users/weasley/Development/IdeaProjects/dtt-spring-boot-parent/ALL_IN_ONE.SQL
- Generate business source code with
DTTthrough yaml configuration
Here is the example of application.yml:
alphahub:
dtt:
code-generator:
is-enable: off
show-code: false
override-exists: false
module-name: dtt
module-package: com.example
module-path: /Users/weasley/Development/IdeaProjects/dtt-spring-boot-parent/dtt-spring-boot-starter-tests/dtt-spring-boot-3-x
base-package: com.example.domain.dtt
base-classes: ""
Full meta data for code-generator configuration
ï¼the classes of Service, Mapper interface, Mapper.xml, The directory structure is as follows:

Next, you can use the generated code in some controller classï¼i.e:
/**
* Some controller
*/
@RestController
@RequestMapping("/api/member")
public class SomeController {
@Autowired
private DttMemberService memberService;
@PostMapping("/save")
@Transactional(rollbackFor = {Exception.class})
public ResponseEntity<Boolean> save(@RequestBody DttMember member) {
boolean save = memberService.save(member);
return ResponseEntity.ok(save);
}
@PutMapping("/update")
@Transactional(rollbackFor = {Exception.class})
public ResponseEntity<Boolean> update(@RequestBody DttMember member) {
boolean updated = memberService.updateById(member);
return ResponseEntity.ok(updated);
}
@GetMapping("/info/{id}")
public ResponseEntity<DttMember> info(@PathVariable Long id) {
DttMember dttMember = memberService.getById(id);
return ResponseEntity.ok(dttMember);
}
@GetMapping("/list/{ids}")
public ResponseEntity<List<DttMember>> list(@PathVariable Long[] ids) {
List<DttMember> list = memberService.listByIds(Arrays.asList(ids));
return ResponseEntity.ok(list);
}
@DeleteMapping("/delete/{ids}")
@Transactional(rollbackFor = {Exception.class})
public ResponseEntity<Boolean> delete(@PathVariable Long[] ids) {
boolean removed = memberService.removeByIds(Arrays.asList(ids));
return ResponseEntity.ok(removed);
}
}
That's the overview for DTT quick start.
Annotation Metadata
EnableDtt
To enable DTT support your applicationï¼annotate on you main class.
| property | type | desc | remark |
|---|---|---|---|
scanBasePackages |
String[] |
The model classes be given | The package permissions are as small as possible. If the scope is too large, DTT will scan all classes in subpackages. |
scanBaseClasses |
Class<?>[] |
base classes to scanï¼optional | You want to specify which model class files generate database tables |
ParserType |
ParserType |
Enumï¼JAVA_DOC,ANNOTATION |
Which parser you want to choose to parse model, default is set to:ParserType.JAVA_DOC, Particularlyï¼if your application is run with type of jar,war,JAVA_DOC will do nothing for this opt. Java doc has advantage of 0-Code injection for your project src. |
dropTableBeforeCreate |
boolean |
Drop oraginal table before create new table | If true, the table created will be drop from database |
@Dtt
Which can annotate on you Java modle class or property of modleï¼Usually used in combination with ParserType=ParserType.ANNOTATION.
| property | type | desc | remark |
|---|---|---|---|
value |
String | when annotated on model class, can be as the commen of table, annotated on model propertyï¼can be as the comment of table column | |
isPrimaryKey |
boolean | Mark whether the current column is the primary key, the default is false |
|
dbDataType |
String | DB data type, i.eï¼MySQLï¼: varchar(64) |
|
defaultValue |
String | default value of current propertyï¼mapping to table column |
Yaml configuration
You can easily use in prefix of alphahub.tt in your porjectï¼Here the fully yaml property with default maybe you can
reference it. you can override in you application.yml if you don't need one of them. i.e:
Particularly. when all-in-one-table set enbled, DTT'll export a file with all-in-one type table DDL statements to
the destination you set in your application.yml file.
Develop Environment
1. Requirments
| items | requirments | remark |
|---|---|---|
| JDK | JDK1.8 or latest | |
| SpringBoot | 2.2.0.RELEASE <= version <= 3.0.0-M3 | |
| IDE | IDEAãEclipse... | |
| Maven | v3.6.5 or latest |
Features of DTT
1 Good partner for RDB data migration
You can easily complete the creation of the target database in the RDB database that DTT has been adapted to without
modifying any source code, and can retain the remark information of each metadata of the old database. The whole process
takes about 20 seconds.
2 Create tables with the type of 0-code injection
Which means DTT do nothing for your source code, you can specify parserType = ParserType.JAVA_DOC in EnableDtt
annotation. you can also make parserType = ParserType.ANNOTATION optional.
3 Export SQL for table's DDL statement to local file
DTT can Export SQL for table's DDL statement to local file thorough yaml configuration optional that you can
modify those DLL statements.
4 Preserve all meta comments for database tables
DTT's parser support parsing the Java documentation.
5 Specifies the character length of the metadata
You can configure for your configuration yaml like this, Here is the link
Example:
alphahub:
dtt:
string-length-mapper:
- database-type: MYSQL
default-text-type: varchar
default-text-length: 256
length-configs:
- text: phone,_tel,telephone,_user,_size
length: 16
- text: _id,_no,number,name,code,_code,_name
length: 64
- text: link,url,_url,_link
length: 128
- text: _msg,message,remark
length: 512
- text: request,response,body,text,content
length: 768
Explanationï¼
Which means when your database is MySQL, A column contains filed of phone, _tel, ... will be defined as type
of varchar(16),if the alphahub.dttstring-length-mapper.length-configs list is not configured, the data type of the
column will be defined as: varchar(256);
6 Automatically infer default values for database table columns
i.e:
- An enum type to illustrate DTT infer default values.
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* ä¼åç±»åæä¸¾
*
* @author weasley
* @version 1.0
* @date 2022/7/9
*/
@Getter
@AllArgsConstructor
public enum MemberType {
ORDINARY("æ®éä¼å"),
STUDENT("å¦çä¼å"),
GUNMETAL("ééä¼å"),
SILVER("ç½é¶ä¼å"),
GOLD("é»éä¼å"),
DIAMOND("é»ç³ä¼å"),
SPORTS("ä½è²ä¼å"),
PLUS("plusä¼å");
/**
* ä¼åæè¿°
*/
private final String desc;
}
- An domain class to infer diffrent table structure between
DTTsupportedRDB
/**
* ç¨æ·ä¿¡æ¯-DttMember
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class DttMember implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主é®id
*/
private Long id;
/**
* ç¨æ·openId
*/
private String openId;
/**
* ç¨æ·æµç§°
*/
private String nickname;
/**
* æ¯å¦å¯ç¨, é»è®¤ï¼1
*/
private Boolean isEnable = true;
/**
* ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00
*/
private BigDecimal balance = BigDecimal.valueOf(0L, 2);
/**
* åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss
*/
private LocalDateTime birthday;
/**
* ä¼åç±»åï¼é»è®¤ï¼ORDINARY
*/
private MemberType memberType = MemberType.ORDINARY;
/**
* ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸
*/
private Integer status = 3;
/**
* è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷
*/
private Integer deleted = 0;
/**
* æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd
*/
private LocalDate registrarDate;
/**
* ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss
*/
private LocalTime accelerateBeginTime;
/**
* ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss
*/
private LocalTime accelerateEndTime;
/**
* ä¿®æ¹æ¶é´
*/
private LocalDateTime updateTime;
}
- For those properties which specified default valueï¼
DTTcan infer the default value for differentRDBwhichDTThas supported as follow:
/**
* ç¨æ·ä¿¡æ¯-DttMember
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class DttMember implements Serializable {
private static final long serialVersionUID = 1L;
/**
* æ¯å¦å¯ç¨, é»è®¤ï¼1
*/
private Boolean isEnable = true;
/**
* ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00
*/
private BigDecimal balance = BigDecimal.valueOf(0L, 2);
/**
* ä¼åç±»åï¼é»è®¤ï¼ORDINARY
*/
private MemberType memberType = MemberType.ORDINARY;
/**
* ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸
*/
private Integer status = 3;
/**
* è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷
*/
private Integer deleted = 0;
}
As you can see the default value specified by DTT in the table DDL statement demonstrate the given 3 types RDB.
(a) DB2
CREATE TABLE "TESTDB"."DTT_MEMBER"
(
"ID" BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
"OPEN_ID" VARCHAR(64) DEFAULT NULL,
"NICKNAME" VARCHAR(64) DEFAULT NULL,
"IS_ENABLE" BOOLEAN DEFAULT true,
"BALANCE" DECIMAL DEFAULT 0.00,
"BIRTHDAY" TIMESTAMP DEFAULT NULL,
"MEMBER_TYPE" VARCHAR(256) DEFAULT 'ORDINARY',
"STATUS" INTEGER DEFAULT 3,
"DELETED" INTEGER DEFAULT 0,
"REGISTRAR_DATE" DATE DEFAULT NULL,
"ACCELERATE_BEGIN_TIME" TIME DEFAULT NULL,
"ACCELERATE_END_TIME" TIME DEFAULT NULL,
"UPDATE_TIME" TIMESTAMP(6) DEFAULT CURRENT TIMESTAMP,
PRIMARY KEY ("ID")
);
COMMENT ON TABLE "TESTDB"."DTT_MEMBER" IS 'ç¨æ·ä¿¡æ¯';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."ID" IS '主é®id';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."OPEN_ID" IS 'ç¨æ·openId';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."NICKNAME" IS 'ç¨æ·æµç§°';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."IS_ENABLE" IS 'æ¯å¦å¯ç¨, é»è®¤ï¼1';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."BALANCE" IS 'ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."BIRTHDAY" IS 'åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."MEMBER_TYPE" IS 'ä¼åç±»åï¼é»è®¤ï¼ORDINARY, Enum type:ORDINARY,STUDENT,GUNMETAL,SILVER,GOLD,DIAMOND,SPORTS,PLUS';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."STATUS" IS 'ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."DELETED" IS 'è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."REGISTRAR_DATE" IS 'æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."ACCELERATE_BEGIN_TIME" IS 'ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."ACCELERATE_END_TIME" IS 'ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss';
COMMENT ON COLUMN "TESTDB"."DTT_MEMBER"."UPDATE_TIME" IS 'ä¿®æ¹æ¶é´';
(b) SQL server
CREATE TABLE [dbo].[dtt_member]
(
[id] bigint PRIMARY KEY NOT NULL,
[open_id] varchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT NULL,
[nickname] varchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS DEFAULT NULL,
[is_enable] tinyint DEFAULT 1,
[balance] money DEFAULT 0.00,
[birthday] datetime2 DEFAULT NULL,
[member_type] varchar(256) DEFAULT 'ORDINARY',
[status] int DEFAULT 3,
[deleted] int DEFAULT 0,
[registrar_date] date DEFAULT NULL,
[accelerate_begin_time] time DEFAULT NULL,
[accelerate_end_time] time DEFAULT NULL,
[update_time] datetime2 DEFAULT NULL
)
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ä¿¡æ¯',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member'
GO
EXEC sp_addextendedproperty
'MS_Description', N'主é®id',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·openId',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'open_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·æµç§°',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'nickname'
GO
EXEC sp_addextendedproperty
'MS_Description', N'æ¯å¦å¯ç¨, é»è®¤ï¼1',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'is_enable'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'balance'
GO
EXEC sp_addextendedproperty
'MS_Description', N'åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'birthday'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åç±»åï¼é»è®¤ï¼ORDINARY, Enum type:ORDINARY,STUDENT,GUNMETAL,SILVER,GOLD,DIAMOND,SPORTS,PLUS',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'member_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'deleted'
GO
EXEC sp_addextendedproperty
'MS_Description', N'æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'registrar_date'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'accelerate_begin_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'accelerate_end_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¿®æ¹æ¶é´',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'update_time'
GO
(c) MySQL
CREATE TABLE IF NOT EXISTS `db_demo`.`dtt_member`
(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®id',
`open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç¨æ·openId',
`nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç¨æ·æµç§°',
`is_enable` tinyint DEFAULT true COMMENT 'æ¯å¦å¯ç¨, é»è®¤ï¼1',
`balance` decimal DEFAULT 0.00 COMMENT 'ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00',
`birthday` datetime DEFAULT NULL COMMENT 'åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss',
`member_type` enum('ORDINARY','STUDENT','GUNMETAL','SILVER','GOLD','DIAMOND','SPORTS','PLUS') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'ORDINARY' COMMENT 'ä¼åç±»åï¼é»è®¤ï¼ORDINARY',
`status` int DEFAULT 3 COMMENT 'ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸',
`deleted` int DEFAULT 0 COMMENT 'è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷',
`registrar_date` date DEFAULT NULL COMMENT 'æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd',
`accelerate_begin_time` time DEFAULT NULL COMMENT 'ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss',
`accelerate_end_time` time DEFAULT NULL COMMENT 'ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'ä¿®æ¹æ¶é´',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='ç¨æ·ä¿¡æ¯-DttMember';
7 Configure precision for high precision data types
- Here is the complete configurations
- The following is an example of the default configuration built into DTT:
alphahub:
dtt:
high-precision-data-mapper:
high-precision-data-type: BigDecimal #The high precision data types of Java
default-integer-length: 10 #The default length of the integer part
default-decimal-length: 6 #The default length of fractional part
precision-configs:
- text: price,amount #The possible fields that need to be inferred, separated by ","(case insensitive)
integer-length: 10 #The length of the integer part of the field
decimal-length: 2 #The length of the fractional part
- Inference description, take the
h2database as an example:
When the fields of the database table mapped by the private properties of your Java object contain price, amount
fields (case-insensitive), the data type of the column will be defined as: NUMERIC(10,2 ), if
the alphahub.dtt.precision-configs list is not configured, the data type of the column will be defined
as: NUMERIC(10,6);
Generally, a high-precision data type is used to define the data type of currency. The default configuration of
DTT's alphahub.dtt.precision-configs includes price, amount, the fields is only applicable to the currency data
precision of CNY , If the developer is using the currency unit of other countries, I strongly recommend that the
developer configure the data precision that matches the business type in their own application to override the default
data precision configuration of DTT built in.
8 Integrate multi-mybatis framework with 0-Code
mybatis: https://github.com/mybatis/spring-boot-startermybatis-plus: https://github.com/baomidou/mybatis-plustk.mybatis: https://search.maven.org/artifact/tk.mybatis/mapper-spring-boot-starterpagehelper: https://search.maven.org/artifact/com.github.pagehelper/pagehelper
9 Built-in mybatis-plus code generator
DTT can help you build an enterprise development framework quickly, you can configure it in your project configuration
yaml file,
i.e:
alphahub:
dtt:
code-generator:
is-enable: on
show-code: false
override-exists: false
module-name: dtt
module-package: com.example
module-path: /Users/weasley/Development/IdeaProjects/dtt-spring-boot-parent/dtt-spring-boot-starter-tests/dtt-spring-boot-3-x
base-package: com.example.domain.dtt
base-classes: ""
Here is the explaination for configuration meta-data
10 Support mybatis create table automatically
-
This feature only available for supported
RDB -
This feature depends on your
springbootmain class or configuration class annotated by@EnableDtt, you don't need to specify any properties of@EnableDtt, and you can set theenabledstatus todisabledthroughyamlconfiguration in different environment of your applicationï¼Default status is enabledï¼. -
Example of disabled
yamlconfiguration
alphahub:
dtt:
mybatis-orm-support:
is-enable: false #Disable DTT to create table during execution SQL lifecycle of mybatis
-
It is recommended to use Dtt annotation to annotate your domain model if your are none native English speaker, the domain model is missing Dtt annotation will cause the table to be created without column metadata comments like
Hibernatecreated without comments. If your English is so well and you know the meaning of each metadata, it is fine not to add them.Here is an example of using a domain object using
@Dtt:
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* ä¼åç±»åæä¸¾
*
* @author weasley
* @version 1.0
* @date 2022/7/9
*/
@Getter
@AllArgsConstructor
public enum MemberType {
ORDINARY("æ®éä¼å"),
STUDENT("å¦çä¼å"),
GUNMETAL("ééä¼å"),
PLUS("plusä¼å");
/**
* ä¼åæè¿°
*/
private final String desc;
}
import cn.alphahub.dtt.plus.annotations.Dtt;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* ç¨æ·ä¿¡æ¯-DttPerson
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Dtt("ç¨æ·ä¿¡æ¯")
public class DttMember implements Serializable {
private static final long serialVersionUID = 1L;
@Dtt(value = "主é®id")
private Long id;
@Dtt(value = "ç¨æ·openId")
private String openId;
@Dtt(value = "ç¨æ·æµç§°")
private String nickname;
@Dtt(value = "æ¯å¦å¯ç¨, é»è®¤ï¼1")
private Boolean isEnable = true;
@Dtt(value = "ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00")
private BigDecimal balance = BigDecimal.valueOf(0L, 2);
@Dtt(value = "åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthday;
@Dtt(value = "ä¼åç±»åï¼é»è®¤ï¼ORDINARY")
private MemberType memberType = MemberType.ORDINARY;
@Dtt(value = "ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸")
private Integer status = 0;
@Dtt(value = "è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷")
private Integer deleted = 0;
@Dtt(value = "æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd")
private LocalDate registrarDate;
@Dtt(value = "ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss")
private LocalTime accelerateBeginTime;
@Dtt(value = "ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss")
private LocalTime accelerateEndTime;
@Dtt(value = "ä¿®æ¹æ¶é´")
private LocalDateTime updateTime;
}
End of this feature introduction, I want to note that in the development environment, the remarks of the data table can
be obtained by parsing Java documentation. In the environment of Jarã warï¼DTT doesn't support parsing Java
documents, so the comments for the created table are missing. If you want to synchronize the table structure
for production environment from Dev environment which created by DTT, then you can ignore to use@Dttannotations
to annotate your domain objectsï¼you can you some RDB tools.
11 Support calling API to create table
API: cn.alphahub.dtt.plus.framework.miscellaneous.DttDefaultConditionalService#manualCreate
/**
* Manually specify a collection of fully qualified Class names to create database tables
*
* @param request The request data for dtt manual automatically create database tables
* @return The list of 'DttManualActEntity'
*/
public List<DttManualActEntity> manualCreate(DttManualActRequest request){}
- Add the annotation
@EnableDttto the startup class of yourspring-bootapplication, i.e:
import cn.alphahub.dtt.plus.entity.DttManualActEntity;
import cn.alphahub.dtt.plus.entity.DttManualActRequest;
import cn.alphahub.dtt.plus.framework.annotations.EnableDtt;
import cn.alphahub.dtt.plus.framework.miscellaneous.DttDefaultConditionalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Some Application
*/
@EnableDtt
@SpringBootApplication
public class SomeApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApplication.class, args);
}
/**
* Some controller
*/
@RestController
@RequestMapping("/api/member")
public static class SomeController {
@Autowired
private DttDefaultConditionalService defaultConditionalService;
@PostMapping("/manual/act")
public List<DttManualActEntity> manualCreateTable(@RequestBody DttManualActRequest request) {
return this.defaultConditionalService.manualCreate(request);
}
}
}
Supported RDB type
| database | version | adaptation |
|---|---|---|
mysql |
5.7+ or latest |
â |
oracle |
11.2.x or latest |
â |
db2 |
11.x or latest |
â |
sqlserver |
14.x or latest |
â |
mariadb |
10.x or latest |
â |
postgresql |
v9.x or latest |
â |
h2 |
- | â |
hsql |
- | â |
derby |
- | â |
Performance
DTT support either create table lazily on demandï¼depends on mybatis frameworkï¼ or eagerly on startup. this chapter
will explore the impact of enabling DTT on application performance from two
perspectives. Here is the tests project
Test platform & environment
| item | value | remark |
|---|---|---|
| Computer System | Mac OS X | MacBook Pro 14 (2021) |
| Architecture | aarch64 | |
| OS Version | 12.5.1 | |
| RAM | 32G | |
| RDB | SQL Server | version: 14.00.3451 |
| JDK | 1.8.0_342 (arm64) | "Azul Systems, Inc." - "Zulu 8.64.0.15" |
| Apache Maven | 3.8.6 | https://maven.apache.org/download.cgi |
| DTT | 1.3.5 | https://search.maven.org/artifact/io.github.weasley-j/dtt-spring-boot-starter |
| spring-boot | 2.7.3 | https://search.maven.org/artifact/org.springframework.boot/spring-boot-starter-parent/2.7.3/pom |
| mybatis-plus-boot-starter | 3.5.2 | https://search.maven.org/artifact/com.baomidou/mybatis-plus-boot-starter |
| mybatis-spring-boot-starter | 2.2.2 | https://search.maven.org/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter |
| pagehelper-spring-boot | 1.4.3 | https://search.maven.org/artifact/com.github.pagehelper/pagehelper-spring-boot |
| mapper-spring-boot-starter | 4.2.1 | https://search.maven.org/artifact/tk.mybatis/mapper-spring-boot-starter |
Create table eagerly on startup
- Enable DTT for your application
- [x] Main class of application
import cn.alphahub.dtt.plus.enums.ParserType;
import cn.alphahub.dtt.plus.framework.annotations.EnableDtt;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableDtt(
scanBasePackages = {
"com.example.domain.dtt", "com.example.domain.order"
},
scanBaseClasses = {},
parserType = ParserType.JAVA_DOC,
dropTableBeforeCreate = true
)
@SpringBootApplication
@MapperScan(basePackages = {"com.example.mapper"})
public class MydttPlus2xTestApp {
public static void main(String[] args) {
SpringApplication.run(MydttPlusTestApplication.class, args);
}
}
# The application.yml of sqlserver
spring:
datasource:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://192.168.31.23:1433;databaseName=dtt_demo;integratedSecurity=false;encrypt=false;
username: SA
password: weasley@dtt123
mybatis-plus:
mapper-locations: classpath:mapper/**/*Mapper.xml,mapper/**/*Dao.xml
type-aliases-package: com.example.domain.dtt,com.example.domain.order
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
alphahub:
dtt:
show-sql: false
all-in-one-table:
enable: true
filename: AllInOne.sql
filepath: /Users/weasley/Downloads
code-generator:
is-enable: on
base-package: com.example.domain.order
module-package: com.example
module-name: order
module-path: /Users/weasley/Development/IdeaProjects/dtt-spring-boot-parent/dtt-spring-boot-starter-tests/dtt-spring-boot-2-x
Note: The property scanBasePackages's value of @EnableDtt is the same as the value
of mybatis-plus.type-aliases-package or mybatis.type-aliases-package . Those classes are mapped to your database
table.
- [x] Start application with Enabling
DTT
As we can see from the image:

2022-08-19 16:56:24.609 INFO 8331 --- [ main] com.example.MydttPlusTestApplication : Started MydttPlusTestApplication in 2.132 seconds (JVM running for 2.598)
2022-08-19 16:56:26.845 INFO 8331 --- [ main] c.a.dtt.plus.framework.InitDttHandler : Auto created tables for '2' seconds. detail: {"dttStartTime":"2022-08-19 16:56:24","dttEndTime":"2022-08-19 16:56:26"}, location: /Users/weasley/Downloads/AllInOne.sql
DTT has done two things in the logger:
(a) Generate Service, Mapper, Mapper.xml source code

(b) created 63 tables based on your domain objects

DTT takes 2 seconds to do what it's supposed to do, which means to use DTT based on your domain objects you just
need to write some Controller to satisfy your business interface, for
example: SomeController
- Disable DTT for your application
- [x] Main class
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.example.mapper"})
public class MydttPlus2xTestApp {
public static void main(String[] args) {
SpringApplication.run(MydttPlusTestApplication.class, args);
}
}

2022-08-19 17:27:42.829 INFO 21286 --- [ main] MydttPlus2xTestApp : Started MydttPlus2xTestApp in 2.122 seconds (JVM running for 2.381)
Started MydttPlusTestApplication in 2.122 seconds without DTT.
- Compare
| APP | Loading type | DTT | Time |
|---|---|---|---|
| MydttPlus2xTestApp | default | NO | 2.122s |
| MydttPlus2xTestApp | eagerly on startup | YES | 2.132s + 2s = 4.132s |
Create table lazily on demand
Create table lazily on demand means that when mybatis executes DDL or DQL statements, if there is no corresponding
table in the database, DTT will be created, and the cache design is used here.
For this step, delete the test table from your SQL server database, clear your console of IDE,
com.example.domain.dtt.DttMember -> dtt_member
(1) Main class
import cn.alphahub.dtt.plus.framework.annotations.EnableDtt;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableDtt
@SpringBootApplication
@MapperScan(basePackages = {"com.example.mapper"})
public class MydttPlus2xTestApp {
public static void main(String[] args) {
SpringApplication.run(MydttPlus2xTestApp.class, args);
}
}
(2) application.yml
logging:
level:
org.springframework.jdbc.core.JdbcTemplate: debug
jdbc.sqltiming: debug
spring:
datasource:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://192.168.31.23:1433;databaseName=dtt_demo;integratedSecurity=false;encrypt=false;
username: SA
password: weasley@dtt123
mybatis-plus:
mapper-locations: classpath:mapper/**/*Mapper.xml,mapper/**/*Dao.xml
type-aliases-package: com.example.domain.dtt,com.example.domain.order
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
alphahub:
dtt:
code-generator:
is-enable: on
base-classes:
- com.example.domain.dtt.DttMember
module-name: dtt
module-package: com.example
module-path: /Users/weasley/Development/IdeaProjects/dtt-spring-boot-parent/dtt-spring-boot-starter-tests/dtt-spring-boot-2-x
- [x] Here is the console for step
(2).

2022-08-19 17:57:41.708 INFO 33463 --- [ main] com.example.MydttPlus2xTestApp : Started MydttPlus2xTestApp in 1.873 seconds (JVM running for 2.129)
Access the same interface twice, simulating DTT to build tables on demand, Here is the API url: http://localhost:8080/api/member/save/no/params
(a) 1st logger:
Create table if donest exists, The concrete DDL implementation delegates to the RDB implementation class.
-08-19 18:10:12.339 INFO 38516 --- [ main] com.example.MydttPlus2xTestApp : Started MydttPlus2xTestApp in 2.448 seconds (JVM running for 2.707)
2022-08-19 18:10:12.344 WARN 38516 --- [ main] c.a.dtt.plus.framework.InitDttHandler : Data model is empty. DTT cannot parse.
2022-08-19 18:10:21.078 INFO 38516 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-08-19 18:10:21.078 INFO 38516 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-08-19 18:10:21.079 INFO 38516 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
JDBC Connection [HikariProxyConnection@1139253693 wrapping ConnectionID:2 ClientConnectionId: f2679647-4094-4f20-a812-ee941a778b4a] will be managed by Spring
2022-08-19 18:10:21.183 INFO 38516 --- [nio-8080-exec-1] c.a.d.p.f.i.DefaultDttMybatisInterceptor : Table of 'dtt_member' not exists, DTT will help you to create it automatically.
2022-08-19 18:10:21.183 INFO 38516 --- [nio-8080-exec-1] c.a.d.p.f.core.DefaultJavaDocParser : Parse Java Doc comments for data table structure informationï¼class 'com.example.domain.dtt.DttMember'
2022-08-19 18:10:21.215 INFO 38516 --- [nio-8080-exec-1] c.a.d.p.f.c.DefaultSqlserverTableHandler : 使ç¨sqlserveré»è®¤å»ºè¡¨å®ç° {"databaseName":"dtt_demo","modelName":"dtt_member","modelComment":"ç¨æ·ä¿¡æ¯","details":[{"isPrimaryKey":true,"databaseDataType":"bigint","javaDataType":"Long","filedName":"id","filedComment":"主é®id","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"varchar(64)","javaDataType":"String","filedName":"open_id","filedComment":"ç¨æ·openId","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"varchar(64)","javaDataType":"String","filedName":"nickname","filedComment":"ç¨æ·æµç§°","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"tinyint","javaDataType":"Boolean","filedName":"is_enable","filedComment":"æ¯å¦å¯ç¨, é»è®¤ï¼1","initialValue":"true"},{"isPrimaryKey":false,"databaseDataType":"money","javaDataType":"BigDecimal","filedName":"balance","filedComment":"ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00","initialValue":"0.00"},{"isPrimaryKey":false,"databaseDataType":"datetime2","javaDataType":"LocalDateTime","filedName":"birthday","filedComment":"åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"varchar('ORDINARY','STUDENT','GUNMETAL','SILVER','GOLD','DIAMOND','SPORTS','PLUS')","javaDataType":"Enum","filedName":"member_type","filedComment":"ä¼åç±»åï¼é»è®¤ï¼ORDINARY","initialValue":"ORDINARY"},{"isPrimaryKey":false,"databaseDataType":"int","javaDataType":"Integer","filedName":"status","filedComment":"ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸","initialValue":"3"},{"isPrimaryKey":false,"databaseDataType":"int","javaDataType":"Integer","filedName":"deleted","filedComment":"è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷","initialValue":"0"},{"isPrimaryKey":false,"databaseDataType":"date","javaDataType":"LocalDate","filedName":"registrar_date","filedComment":"æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"time","javaDataType":"LocalTime","filedName":"accelerate_begin_time","filedComment":"ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"time","javaDataType":"LocalTime","filedName":"accelerate_end_time","filedComment":"ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss","initialValue":"NULL"},{"isPrimaryKey":false,"databaseDataType":"datetime2","javaDataType":"LocalDateTime","filedName":"update_time","filedComment":"ä¿®æ¹æ¶é´","initialValue":"NULL"}]}
2022-08-19 18:10:21.229 INFO 38516 --- [nio-8080-exec-1] c.a.d.p.f.core.DefaultTemplateResolver : æ°æ®åºå»ºè¡¨è¯å¥:
CREATE TABLE [dbo].[dtt_member]
(
[id] bigint PRIMARY KEY NOT NULL,
[open_id] varchar(64) COLLATE Chinese_PRC_CI_AS DEFAULT NULL,
[nickname] varchar(64) COLLATE Chinese_PRC_CI_AS DEFAULT NULL,
[is_enable] tinyint DEFAULT 1,
[balance] money DEFAULT 0.00,
[birthday] datetime2 DEFAULT NULL,
[member_type] varchar(256) DEFAULT 'ORDINARY',
[status] int DEFAULT 3,
[deleted] int DEFAULT 0,
[registrar_date] date DEFAULT NULL,
[accelerate_begin_time] time DEFAULT NULL,
[accelerate_end_time] time DEFAULT NULL,
[update_time] datetime2 DEFAULT NULL
)
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ä¿¡æ¯',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member'
GO
EXEC sp_addextendedproperty
'MS_Description', N'主é®id',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·openId',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'open_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·æµç§°',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'nickname'
GO
EXEC sp_addextendedproperty
'MS_Description', N'æ¯å¦å¯ç¨, é»è®¤ï¼1',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'is_enable'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ç§¯åä½é¢, é»è®¤ï¼0.00',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'balance'
GO
EXEC sp_addextendedproperty
'MS_Description', N'åºçæ¥æï¼æ ¼å¼ï¼yyyy-MM-dd HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'birthday'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åç±»åï¼é»è®¤ï¼ORDINARY, Enum type:ORDINARY,STUDENT,GUNMETAL,SILVER,GOLD,DIAMOND,SPORTS,PLUS',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'member_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ç¨æ·ç¶æï¼0 æ£å¸¸(é»è®¤)ï¼1 å·²å»ç»ï¼2 è´¦å·å·²å°ï¼3 è´¦å·å¼å¸¸',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'è´¦æ·æ³¨éç¶æï¼0 æªæ³¨éï¼é»è®¤ï¼ï¼1 已鿷',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'deleted'
GO
EXEC sp_addextendedproperty
'MS_Description', N'æ³¨åæ¶é´ï¼æ ¼å¼: yyyy-MM-dd',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'registrar_date'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åå éå¼å§æ¶é´, æ ¼å¼ï¼HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'accelerate_begin_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¼åå éç»ææ¶é´, æ ¼å¼ï¼HH:mm:ss',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'accelerate_end_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'ä¿®æ¹æ¶é´',
'SCHEMA', N'dbo',
'TABLE', N'dtt_member',
'COLUMN', N'update_time'
GO
Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
2022-08-19 18:10:21.343 DEBUG 38516 --- [nio-8080-exec-1] o.s.jdbc.core.JdbcTemplate : Executing SQL batch update of 15 statements
Transaction synchronization resuming SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
==> Preparing: SELECT MAX(ID) id FROM dtt_member
==> Parameters:
<== Columns: id
<== Row: null
<== Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
JDBC Connection [HikariProxyConnection@1139253693 wrapping ConnectionID:2 ClientConnectionId: f2679647-4094-4f20-a812-ee941a778b4a] will be managed by Spring
==> Preparing: INSERT INTO dtt_member ( id, open_id, nickname, is_enable, balance, birthday, member_type, status, deleted, registrar_date, accelerate_begin_time, accelerate_end_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 1560569852266041346(Long), fawezOE5sT(String), èéå(String), true(Boolean), 865(BigDecimal), 2022-08-19T18:10:21.135(LocalDateTime), STUDENT(String), 0(Integer), 1(Integer), 2022-08-19(LocalDate), 18:10:21.135(LocalTime), 18:10:21.135(LocalTime), 2022-08-19T18:10:21.135(LocalDateTime)
2022-08-19 18:10:21.449 INFO 38516 --- [nio-8080-exec-1] com.example.controller.SomeController : {"id":1560569852266041346,"openId":"fawezOE5sT","nickname":"èéå","isEnable":true,"balance":865,"birthday":"2022-08-19 18:10:21","memberType":"STUDENT","status":0,"deleted":1,"registrarDate":"2022-08-19","accelerateBeginTime":"18:10:21","accelerateEndTime":"18:10:21","updateTime":"2022-08-19 18:10:21"}
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
(b) 2nd logger
Cause by table exists, DTT does nothing.
2022-08-19 18:10:21.449 INFO 38516 --- [nio-8080-exec-1] com.example.controller.SomeController : {"id":1560569852266041346,"openId":"fawezOE5sT","nickname":"èéå","isEnable":true,"balance":865,"birthday":"2022-08-19 18:10:21","memberType":"STUDENT","status":0,"deleted":1,"registrarDate":"2022-08-19","accelerateBeginTime":"18:10:21","accelerateEndTime":"18:10:21","updateTime":"2022-08-19 18:10:21"}
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7ab15e2a]
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5167ea53]
JDBC Connection [HikariProxyConnection@1537179939 wrapping ConnectionID:2 ClientConnectionId: f2679647-4094-4f20-a812-ee941a778b4a] will be managed by Spring
==> Preparing: SELECT MAX(ID) id FROM dtt_member
==> Parameters:
<== Columns: id
<== Row: 1560569852266041346
<== Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5167ea53]
JDBC Connection [HikariProxyConnection@1537179939 wrapping ConnectionID:2 ClientConnectionId: f2679647-4094-4f20-a812-ee941a778b4a] will be managed by Spring
==> Preparing: INSERT INTO dtt_member ( id, open_id, nickname, is_enable, balance, birthday, member_type, status, deleted, registrar_date, accelerate_begin_time, accelerate_end_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 1560569852266041347(Long), fawezOE5sT(String), èéå(String), true(Boolean), 865(BigDecimal), 2022-08-19T18:13:45.066(LocalDateTime), STUDENT(String), 0(Integer), 1(Integer), 2022-08-19(LocalDate), 18:13:45.066(LocalTime), 18:13:45.066(LocalTime), 2022-08-19T18:13:45.066(LocalDateTime)
2022-08-19 18:13:45.082 INFO 38516 --- [nio-8080-exec-3] com.example.controller.SomeController : {"id":1560569852266041347,"openId":"fawezOE5sT","nickname":"èéå","isEnable":true,"balance":865,"birthday":"2022-08-19 18:13:45","memberType":"STUDENT","status":0,"deleted":1,"registrarDate":"2022-08-19","accelerateBeginTime":"18:13:45","accelerateEndTime":"18:13:45","updateTime":"2022-08-19 18:13:45"}
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5167ea53]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5167ea53]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5167ea53]
- [x] Console of defaultï¼Without DTTï¼

2022-08-19 17:52:56.045 INFO 31535 --- [ main] com.example.MydttPlus2xTestApp : Started MydttPlus2xTestApp in 1.293 seconds (JVM running for 1.55)
(3) Compare
| APP | Loading type | DTT | Time |
|---|---|---|---|
| MydttPlus2xTestApp | default | NO | 1.293s |
| MydttPlus2xTestApp | lazily on demand | YES | 1.873s |
From the data comparison in the above table, it is easy to see that lazily on demand has little effect on performance.
The test is made under the circumstances where personal energy and time are limited. Please forgive me if there are some inadequacies.
Contribute your code
todo
Question&Answer
- Those
ORMframeworks which can be integratedDTTwith0-Code?
mybatis: https://github.com/mybatis/spring-boot-startermybatis-plus: https://github.com/baomidou/mybatis-plustk.mybatis: https://search.maven.org/artifact/tk.mybatis/mapper-spring-boot-starterpagehelper: https://search.maven.org/artifact/com.github.pagehelper/pagehelper
Source code quality


Credits
- Java document analyse
com.github.therapi:therapi-runtime-javadoc
- Template engine language
org.apache.velocity:velocity-engine-core
- jsqlparser
