Automate CRUD Code Generation for Java Backend Projects in Minutes
This article introduces a self‑hosted tool that automatically generates entity classes, DAO interfaces, service implementations, and controller code for Java backend projects, dramatically reducing the time spent creating tables, SQL, and boilerplate code while offering customizable templates and dynamic parameters.
Origin
While working on a project that required more than 20 new database tables, I realized that creating entity classes, CRUD interfaces, and SQL scripts for each table consumes about two hours per table, turning a week‑long effort into a tedious slog.
To solve this, I built a tool that generates all the necessary business code automatically.
The tool is available at https://utilsbox.cn/?app=bizcode and the source code is open‑source on GitHub: https://github.com/GooseCoding/utilsbox .
Usage Demonstration
1. Create a new table by entering its name and Chinese description.
2. Add fields to the table, similar to any database UI.
3. Click “One‑Click Generate Code”.
The generated code includes DB layer, business layer, and controller layer files.
All SQL statements, entity classes, DAO interfaces, service interfaces, service implementations, and controller classes are produced automatically.
If you already have an existing table, you can paste its CREATE TABLE SQL into the tool; it will parse the schema and generate the corresponding code.
General Thoughts
The tool works well for my own projects, but to serve a broader audience I added a template configuration feature because different companies have different project structures and coding conventions.
In the “Code Template Configuration” dialog you can add, delete, and edit code categories and individual templates.
Design
The code generator works by combining user‑defined templates with dynamic parameters. The core mechanism is simple: match placeholders and replace them with actual values.
Dynamic parameters include table name, field names, data types, timestamps, etc. Users can define templates that contain these placeholders, and the tool substitutes them at generation time.
Example Template
/**
* $table_desc$Model模型
* Created by 创建人 on $current_time$.
*/
public class $table_name_hump_A$Model extends ToString {
}The placeholders $table_desc$, $current_time$, and $table_name_hump_A$ are replaced with the table’s Chinese description, the current timestamp, and the table name in PascalCase, respectively.
Code Generation Templates
Below are several default templates that the tool ships with. They cover CREATE TABLE SQL, entity classes, DAO interfaces, MyBatis XML mappers, model converters, service implementations, and REST controllers.
CREATE TABLE SQL Template
CREATE TABLE `$table_name$` (
$create_table_field_list$
PRIMARY KEY (`$primary_key$`)
) ENGINE=$db_engine$ DEFAULT CHARSET=$db_encoded$;Entity Class Template
/**
* $table_desc$DTO模型
* Created by 创建人 on $current_time$.
*/
public class $table_name_hump_A$DO {
$member_param_list$
$get_set_method_list$
}DAO Interface Template (MyBatis)
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* $table_desc$DB接口
* Created by 创建人 on $current_time$
*/
@Mapper
public interface $table_name_hump_A$DAO {
int insert($table_name_hump_A$DO data);
int update($table_name_hump_A$DO data);
List<$table_name_hump_A$DO> pageQuery(Map param);
Long pageQueryCount(Map param);
$table_name_hump_A$DO queryById(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
$table_name_hump_A$DO queryByIdLock(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
}MyBatis XML Mapper Template
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.$table_name_hump_A$DAO">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO $table_name$($insert_field_name_list$) VALUES ($insert_field_value_list$);
</insert>
<update id="update">
UPDATE $table_name$ SET $update_field_list$ WHERE $primary_key$ = #{$primary_key_hump$};
</update>
<select id="pageQuery" resultType="com.xxx.$table_name_hump_A$DO">
SELECT $select_field_list$ FROM $table_name$ WHERE 1=1 $while_field_list$
ORDER BY $primary_key$ DESC
<if test="pageIndex != null and pageSize != null">
LIMIT #{offset},#{rows}
</if>
</select>
<select id="pageQueryCount" resultType="java.lang.Long">
SELECT COUNT(1) as total FROM $table_name$ WHERE 1=1 $while_field_list$
</select>
<select id="queryById" resultType="com.xxx.$table_name_hump_A$DO">
SELECT $select_field_list$ FROM $table_name$ WHERE $primary_key$ = #{$primary_key_hump$};
</select>
<select id="queryByIdLock" resultType="com.xxx.$table_name_hump_A$DO">
SELECT $select_field_list$ FROM $table_name$ WHERE $primary_key$ = #{$primary_key_hump$} FOR UPDATE;
</select>
</mapper>Model Converter Template
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* $table_desc$ 模型转换器
* Created by 创建人 on $current_time$
*/
public class $table_name_hump_A$Converter {
public static $table_name_hump_A$DO toDo($table_name_hump_A$DTO source) {
$table_name_hump_A$DO target = new $table_name_hump_A$DO();
$converter_source_to_target_params_list$
return target;
}
public static $table_name_hump_A$DTO toDto($table_name_hump_A$DO source) {
$table_name_hump_A$DTO target = new $table_name_hump_A$DTO();
$converter_source_to_target_params_list$
return target;
}
public static List<$table_name_hump_A$DTO> toDtoList(List<$table_name_hump_A$DO> data) {
if (CollectionUtils.isEmpty(data)) {
return null;
}
List<$table_name_hump_A$DTO> list = new ArrayList<>();
for ($table_name_hump_A$DO item : data) {
list.add($table_name_hump_A$Converter.toDto(item));
}
return list;
}
}Service Implementation Template
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* $table_desc$ 业务实现
* Created by 创建人 on $current_time$
*/
@Service
public class $table_name_hump_A$ServiceImpl implements $table_name_hump_A$Service {
private static final Logger LOGGER = LoggerFactory.getLogger($table_name_hump_A$ServiceImpl.class);
@Resource
private $table_name_hump_A$DAO $table_name_hump$DAO;
@Override
public CommonResult create(JSONObject request) {
CommonAssert.isNoEmptyObj(request, "请求参数不可空");
$table_name_hump_A$DTO dto = JSON.toJavaObject(request, $table_name_hump_A$DTO.class);
$biz_check_required_params$
$table_name_hump_A$DO dataDo = $table_name_hump_A$Converter.toDo(dto);
int count = $table_name_hump$DAO.insert(dataDo);
CommonAssert.isTrue(count > 0, "创建失败,请重试");
return new CommonResult(dataDo.get$primary_key_hump_A$());
}
// modify, pageQuery, queryById methods omitted for brevity
}Controller Template
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* $table_desc$ HTTP请求控制器
* Created by 创建人 on $current_time$.
*/
@CrossOrigin
@RestController
@RequestMapping(value = "/$table_name_hump$/")
public class $table_name_hump_A$Controller {
private static final Logger LOGGER = LoggerFactory.getLogger($table_name_hump_A$Controller.class);
@Resource
private $table_name_hump_A$Service $table_name_hump$Service;
@RequestMapping(value = "create.json", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object create(@RequestBody JSONObject request) {
return CommonTemplate.run(LOGGER, new CommonTemplate() {
@Override
protected Object business() {
return $table_name_hump$Service.create(request);
}
}, request);
}
// modify, pageQuery, queryById methods omitted for brevity
}Dynamic Parameters
$table_name$ : raw table name entered by the user.
$table_name_hump$ : camelCase version of the table name (e.g., goods_order → goodsOrder).
$table_name_hump_A$ : PascalCase version of the table name (e.g., goods_order → GoodsOrder).
$field_name$ : raw field name.
$field_name_hump$ : camelCase field name.
$field_name_hump_A$ : PascalCase field name.
$field_type_java$ : Java type mapped from the selected DB type (e.g., VARCHAR → String).
$primary_key$ : primary key column name.
$primary_key_hump$ : camelCase primary key name.
$primary_key_hump_A$ : PascalCase primary key name.
$primary_key_type_java$ : Java type of the primary key.
$insert_field_name_list$ : comma‑separated list of non‑primary‑key column names.
$insert_field_value_list$ : MyBatis placeholders for non‑primary‑key values.
$update_field_list$ : SET clause for UPDATE statements (excluding primary key).
$select_field_list$ : comma‑separated list of all column names.
$where_field_list$ : conditional WHERE clauses generated per field.
$create_table_field_list$ : column definitions for CREATE TABLE.
$current_time$ : current timestamp (yyyy‑MM‑dd HH:mm:ss).
$java_type_adapter_assert_method$ : selects the appropriate validation method based on Java type.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
