1. What is Kotlin?

Kotlin is a new JVA-BASED programming language developed in 2010 by JetBrains, the company behind IntelliJ IDEA, and has been open source since 2012.

Kotlin can be compiled to Java bytecode or JavaScript, making it easy to run on devices without a JVM.

Kotlin is a general-purpose, open source, static, utility programming language for both the JVM and Android with object-oriented and functional programming capabilities. It focuses on interactivity, security, and clarity and tool support.

2. Characteristics of Kotlin

1. Simplicity: Greatly reduce the amount of boilerplate code.

2, security: avoid null pointer exceptions and other errors of the whole class.

Interoperability: Take advantage of existing libraries in the JVM, Android, and browsers.

4. Tool-friendly: Use any Java IDE or use the command line to build.

3, MybatisPlus

MyBatisPlus (MP for short) is a MyBatis enhancement tool, on the basis of MyBatis only do enhancement do not change, to simplify the development and improve efficiency.

4. Features of MybatisPlus

No intrusion: only enhancements are made, no changes are made, and its introduction will not affect the existing project, as smooth as silk

Low loss: Basic CURD will be injected automatically upon startup, with basically no loss in performance and direct object-oriented operation

Powerful CRUD operations: built-in universal Mapper, universal Service, only through a small amount of configuration can achieve a single table most CRUD operations, more powerful condition constructor, to meet all types of use requirements

Support Lambda form call: through Lambda expressions, it is convenient to write all kinds of query conditions, without worrying about field write errors

Support automatic generation of primary keys: support up to four primary key policies (including distributed unique ID generator – Sequence), can be freely configured, perfect solution to the primary key problem

Support for ActiveRecord mode: Support for ActiveRecord form calls, entity classes only need to inherit from Model classes to perform powerful CRUD operations

Support custom global universal operations: support Write once (use anywhere)

Built-in code generator: using * code or Maven plug-in can quickly generate Mapper, Model, Service, Controller layer code, support template engine, more than a lot of custom configuration you to use

Built-in paging plug-in: Based on MyBatis physical paging, developers do not need to care about specific operations, after configuring the plug-in, write paging is equal to ordinary List query

The paging plug-in supports a variety of databases: MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer, etc

Built-in performance analysis plug-in: outputs Sql statements and their execution time. It is recommended to enable this function during development and testing to quickly find out slow queries

Built-in global interception plug-in: provides intelligent analysis and blocking of delete and UPDATE operations on all tables, and can customize interception rules to prevent misoperations

5. Use Kotlin code generation

The first is the dependency of Mybatis – Plus:

< the dependency > < groupId > com. Baomidou < / groupId > < artifactId > mybatis - plus - generator < / artifactId > < version > 3.3.2 rainfall distribution on 10-12 < / version > </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>Copy the code

Let’s get down to business:

Key points on the website:

Effect:

Code examples:

GeneratorFactory.kt

Funmain (args: Array<String>) {generator()} fun generator(){println("begin generating") val projectPath = System.getproperty ("user.dir") var MPG = AutoGenerator() var globalConfig = globalConfig () globalconfig.iskotlin Author = "XXXXXX" // author Globalconfig. isOpen = false globalconfig.outputDir = System. GetProperty (" user. Dir ") + "/ SRC/main/kotlin" / / create address globalConfig isFileOverride = true globalConfig. IdType = IdType.AUTO globalConfig.xmlName = "%sMapper" globalConfig.mapperName = "%sMapper" globalConfig.serviceName="%sService" globalConfig.serviceImplName = "%sServiceImpl" globalConfig.controllerName = "%sController" globalConfig.isBaseColumnList = true globalConfig.isBaseResultMap = true globalConfig.dateType= DateType.ONLY_DATE mpg.globalConfig = globalConfig var dsc = DataSourceConfig() dsc.dbType = DbType.POSTGRE_SQL dsc.driverName = Org. Postgresql. "Driver" DSC. Url = "JDBC: postgresql: / / 10.4.2.6:15432 / smartpark? useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8" dsc.username = "liantu" dsc.password = "liantu123456" Dsc.schemaname = "vehicle" mpg.dataSource = DSC // var PC = PackageConfig(); // pc.setModulename (scanner(" module name ")); PC. The parent = "com. Example. Kotlin01. Kotlinns" MPG. PackageInfo = PC / / custom configuration val CFG: InjectionConfig = object: InjectionConfig() { override fun initMap() { // to do nothing } } val focList: MutableList<FileOutConfig> = ArrayList() focList.add(object : FileOutConfig("/templates/mapper.xml.ftl") { override fun outputFile(tableInfo: TableInfo): String? {/ / custom input file name return (projectPath. The toString () + "/ SRC/main/resources/mapper/" + tableInfo. GetEntityName () +" mapper "+ DOT_XML)}}) //config xmlTemplate and outpath cfg.fileOutConfigList = focList MPG = TemplateConfig() tc.entityKt="/templates/entity.kt" tc.mapper="/templates/mapper.java" tc.controller="/templates/controller.java" mpg.template=tc var strategy=StrategyConfig() strategy.naming= NamingStrategy.underline_to_camel strategy.columnNaming=NamingStrategy.underline_to_camel strategy.isRestControllerStyle=true strategy.isControllerMappingHyphenStyle=true var sum=StringBuffer() sum.append(pc.moduleName).append("_") strategy.setTablePrefix(sum.toString()) mpg.strategy = strategy mpg.templateEngine  = FreemarkerTemplateEngine() mpg.execute(); }Copy the code

6. On custom templates

Custom templates can be found to modify the official!

The first step is to find the Mybatis- Plus package

Copy and modify it

entity.kt.ftl

package ${package.Entity} <#list table.importPackages as pkg> import ${pkg} </#list> import com.baomidou.mybatisplus.annotation.* <#if swagger2> import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; </#if> /** * <p> * ${table.comment} * </p> * * @author ${author} * @since ${date} */ @TableName("${table.name}") <#if Swagger2 > @apiModel (value="${entity} object ", description="${table.comment! }") </#if> <#if superEntityClass?? > class ${entity} : ${superEntityClass}<#if activeRecord><${entity}></#if> { <#elseif activeRecord> class ${entity} : Model<${entity}>() { <#else> class ${entity} : Serializable {< / # if > < # -- -- -- -- -- -- -- -- -- -- -- BEGIN field to iterate over -- -- -- -- -- -- -- -- -- -- > < # list table. The fields as field > < # if field. KeyFlag > <#assign keyPropertyName="${field.propertyName}"/> </#if> <#if field.comment! ? length gt 0> <#if swagger2> @ApiModelProperty(value = "${field.comment}") <#else> /** * ${field.comment} */ </#if> < / # if > < # if field. KeyFlag > < # - primary key - > < # if field. KeyIdentityFlag > @ TableId (value = "${field. AnnotationColumnName}", type = IdType.AUTO) <#elseif idType ??> @TableId(value = "${field.annotationColumnName}", Type = IdType ${IdType}) < # elseif field. The convert > @ TableId (" ${field. AnnotationColumnName} ") < / # if > < # - ordinary field - > < # elseif Field. The fill?? > < # -- -- -- -- -- -- there is the fields Settings -- -- -- -- - > < # if field. The convert > @ TableField (value = "${field. AnnotationColumnName}", fill = FieldFill.${field.fill}) <#else> @TableField(fill = FieldFill.${field.fill}) </#if> <#elseif field.convert> @ TableField (" ${field. AnnotationColumnName} ") < / # if > < # - optimistic locking annotations - > < # if (versionFieldName!" ") == field.name> @version </#if> <#-- logicDeleteFieldName! ") == field.name> @TableLogic </#if> <#if field.propertyType == "Integer"> var ${field.propertyName}: Int? = null <#else> var ${field.propertyName}: ${field. PropertyType}? = null < / # if > < / # list > < # -- -- -- -- -- -- -- -- -- -- -- END field to iterate over -- -- -- -- -- -- -- -- -- -- > < # if entityColumnConstant > companion object { <#list table.fields as field> const val ${field.name?upper_case} : String = "${field.name}" </#list> } </#if> <#if activeRecord> override fun pkVal(): Serializable? { <#if keyPropertyName??> return ${keyPropertyName} <#else> return null </#if> } </#if> override fun toString(): String { return "${entity}{" + <#list table.fields as field> <#if field_index==0> "${field.propertyName}=" + ${field.propertyName} + <#else> ", ${field.propertyName}=" + ${field.propertyName} + </#if> </#list> "}" } }Copy the code

mapper.java.ftl

package ${package.Mapper}; import ${package.Entity}.${entity}; import ${superMapperClassPackage}; import org.apache.ibatis.annotations.Mapper /** * <p> * ${table.comment! } Mapper interface ${table. MapperName} : ${superMapperClass}<${entity}> <#else> public interface ${table.mapperName} extends ${superMapperClass}<${entity}> { } </#if>Copy the code

Conclusion shows that

DbType = dbType.MYSQL as needed

For a postgresQL database, if the schema is not public, you need to specify schemaName. If you do not specify schemaName, the default schema is public.

dsc.dbType = DbType.POSTGRE_SQL
        dsc.driverName = "org.postgresql.Driver"
        dsc.url = "jdbc:postgresql://ip:port/db"
        dsc.username = "aaaa"
        dsc.password = "bbbb"
        dsc.schemaName = "cccc"
Copy the code

Globalconfig. author = “loulvlin” author needs its own name (for comment)

If you don’t want to generate XML, just comment out the following two lines of code:

//config xmltemplate and outpath cfg.fileOutConfigList = focList mpg. CFG = CFGCopy the code

If you do not want to generate a Controller Service serviceImpl mapper Entity, set the TemplateConfig set method to NULL as follows

mpg.template = TemplateConfig().setXml(null)
                .setController(null)
                .setService(null)
                .setServiceImpl(null)
                .setMapper(null)
                .setEntity(null)
                .setEntityKt(null)
Copy the code

Configure the table and prefix that need to be automatically generated. If the prefix is configured, no prefix will appear in the generated Entity name

sc.setTablePrefix("sys")
        sc.setInclude("sys_case_dict")
Copy the code

Configure tables that require automatic code generation (multiple)

sc.setTablePrefix("sys")
        sc.setInclude("sys_case_dict","sys_case_dict1","sys_case_dict2","sys_case_dict3")
Copy the code

Define a base class for a Service or Controller (as needed)

sc.superControllerClass = "com.aos.base.controller.BaseController"
        sc.superServiceClass = "com.aos.base.service.BaseService"
Copy the code

The generated entity needs to be preceded by an Open keyword, for redis serialization

Generated Entity field type LocalDateTime change to Date(java.util)

@TableName("sys_case_dict") open class Xxxxxx : Serializable {/** * primary key (generated by autoincrement) */ @tableId (value = "id", type = idtype.auto) var id: Int? = null /** * createTime */ var createTime: Date? = null /** * modifyTime: Date? = null }Copy the code

end~