代码生成器可以很大程度提高开发效率。特别是实体类(Domain)与Mapper.xml中实体类属性与数据库字段的对应关系,以及常用的insert、update语句,这些都是重复性工作,手动编写非常枯燥且容易出错。
MyBatisPlus的一个重要作用就是不用编写Mapper.xml。但如果这些代码都可以自动生成,而且修改表结构后,重新生成会自动进行维护(包括Domain实体类),那么使用MyBatisPlus就不是非常必要了。
MyBatisPlus的另一个重要功能是条件构造器,可以灵活构造查询条件,而不需要编写sql代码。UJCMS则设计了使用更为方便的查询解析器,可以在页面设定查询条件,使得后台管理中任意字段的查询功能,都不需要后台额外编写代码。
以上的设计,解决了MyBatis的主要的痛点。这是UJCMS直接使用MyBatis而没有使用MyBatisPlus的主要原因。且直接使用MyBatis,可以对框架进行更细致的控制。
代码生成器基于MyBatis官方的代码生成插件mybatis-generator
。在官方插件的基础上进行了增强,可以生成更多的类和代码,并且对生成的内容进行了优化。
修改以下两个文件,填写正确的数据库URL地址、数据库用户名、数据库密码。
src/test/resources/generatorCoreConfig.xml
src/test/resources/generatorExtConfig.xml
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/ujcms?serverTimezone=UTC" userId="ujcms" password="password"/>
修改代码生成配置文件,加入需要生成代码的表:
src/test/resources/generatorExtConfig.xml
<generatorConfiguration>
<context>
...
<table tableName="ujcms_example" domainObjectName="Example"/>
...
</context>
</generatorConfiguration>
运行src/test/java/com.ujcms.generator.CodeGenerator
类,即可生成代码。
如表结构有改动,则可在改动后,再次运行代码生成器,会自动更新domain和mapper.xml里相应的字段。
注:如果运行代码生成器导致修改系统中原有代码,可以将其它<table tableName="..."
项注释掉,只保留需要生成的表。
代码生成器会生成以下类文件:
com.ujcms.cms.ext.domain.base.ExampleBase
每次运行生成器,都会生成这个类。不要手动修改这个类,否则会被生成器覆盖。com.ujcms.cms.ext.domain.Example
只在第一次运行时生成,可以修改。com.ujcms.cms.ext.mapper.ExampleMapper
只在第一次运行时生成,可以修改。src/main/resources/com/ujcms/cms/ext/mapper/ExampleMapper.xml
修改表结构后,再次运行生成器,生成会自动维护部分代码,可以修改。com.ujcms.cms.ext.service.ExampleService
只在第一次运行时生成,可以修改。com.ujcms.cms.ext.service.args.ExampleArgs
只在第一次运行时生成,可以修改。com.ujcms.cms.ext.web.backendapi.ExampleController
只在第一次运行时生成,可以修改。ExampleBase
由代码生成器根据数据库字段维护,修改数据库表结构后,再次运行代码生成器即可。如需要增加额外的代码,可修改它的子类Example
。
ExampleMapper.xml
最为特殊,也是灵魂所在。修改表结构后,再次运行生成器,生成会自动维护BaseResultMap
Column_List
insert
update
标签内容。但其余部分代码不会被修改或覆盖,所以可以增加额外代码。
<generatorConfiguration>
<context>
...
<table tableName="ujcms_example" domainObjectName="Example">
<!-- 是否生成Service类。默认:true -->
<property name="service" value="false"/>
<!-- 是否生成Controller类。默认:true -->
<property name="controller" value="false"/>
<!-- 是否需要分页。某些表数据较少(如字典、角色),不需要分页。默认:true -->
<property name="pageable" value="false"/>
</table>
...
</context>
</generatorConfiguration>