寫了個工具,讓 CRUD 開發(fā)效率提升100倍,開源咯!
大家好,我是互聯(lián)網(wǎng)架構(gòu)師!
1緣起
部署后的,可直接使用:
https://utilsbox.cn/
2使用演示
下面給大家演示一下
假設(shè)我們現(xiàn)在創(chuàng)建一個商品表
首先填寫表名和表的中文名稱
然后我們添加商品表對應(yīng)的字段,這些操作和我們?nèi)粘J褂玫臄?shù)據(jù)庫工具差不多
把字段填寫好了之后,點(diǎn)擊“一鍵生成代碼”
這是什么概念呢
現(xiàn)在我們只需要把這些代碼拷貝到項(xiàng)目里,簡單設(shè)置一下類的引用,增刪改查這些基本功能,就已經(jīng)可以直接給前端去調(diào)用了。
3通用性的思考
4代碼生成的原理
/**
* $table_desc$Model模型
* Created by 創(chuàng)建人 on $current_time$.
*/
public class $table_name_hump_A$Model extends ToString{
}
可以看到,模版里分別使用了$table_desc$(表中文名)、$current_time$(當(dāng)前時間)、$table_name_hump_A$(表名轉(zhuǎn)首字母大寫駝峰) 這三個動態(tài)參數(shù)。
表名 = goods_order、表中文名 = 商品訂單 時,代碼生成的結(jié)果如下所示:
/**
* 商品訂單Model模型
* Created by 創(chuàng)建人 on 2023-02-05 17:12:32.
*/
public class GoodsOrderModel extends ToString{
}
動態(tài)參數(shù)部分,全部替換成了我們輸入的表信息。
5代碼模版參考
建表SQL模版
CREATE TABLE `$table_name$` (
$create_table_field_list$
PRIMARY KEY (`$primary_key$`)
) ENGINE=$db_engine$ DEFAULT CHARSET=$db_encoded$;
實(shí)體類模版
主體
/**
* $table_desc$DTO模型
* Created by 創(chuàng)建人 on $current_time$.
*/
public class $table_name_hump_A$DO {
$member_param_list$
$get_set_method_list$
}
成員代碼塊 成員變量列表(member_param_list)
/** $field_comment$ */
private $field_type_java$ $field_name_hump$;
成員代碼塊 GetSet方法列表(get_set_method_list)
public $field_type_java$ get$field_name_hump_A$() {
return $field_name_hump$;
}
public void set$field_name_hump_A$($field_type_java$ $field_name_hump$) {
this.$field_name_hump$ = $field_name_hump$;
}
接口類模版(DB層)
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 創(chuàng)建人 on $current_time$
*/
@Mapper
public interface $table_name_hump_A$DAO {
/**
* 添加
* @param data
* return 影響行數(shù)
*/
int insert($table_name_hump_A$DO data);
/**
* 修改
* @param data
* return 影響行數(shù)
*/
int update($table_name_hump_A$DO data);
/**
* 分頁查詢
* @param param
* return 結(jié)果列表
*/
List<$table_name_hump_A$DO> pageQuery(Map param);
/**
* 查詢count
* @param param
* return count條數(shù)
*/
Long pageQueryCount(Map param);
/**
* 根據(jù)ID查詢
* @param id
* return 結(jié)果DO對象
*/
$table_name_hump_A$DO queryById(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
/**
* 根據(jù)ID查詢(帶鎖)
* @param id
* return 結(jié)果DO對象
*/
$table_name_hump_A$DO queryByIdLock(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
}
CRUD SQL模版
<?xml version="1.0" encoding="UTF-8"?>
<!-- $table_name_hump_A$Mapper.xml -->
<!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>
模型轉(zhuǎn)換器模版
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* $table_desc$模型轉(zhuǎn)換器
* Created by 創(chuàng)建人 on $current_time$
*/
public class $table_name_hump_A$Converter {
/**
* dto轉(zhuǎn)do
* @param source
* return do模型
*/
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;
}
/**
* do轉(zhuǎn)dto
* @param source
* return dto模型
*/
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;
}
/**
* do list 轉(zhuǎn) dto
* @param data
* return list dto模型
*/
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;
}
}
成員代碼塊 模型轉(zhuǎn)換器參數(shù)列表(converter_source_to_target_params_list)
target.set$field_name_hump_A$(source.get$field_name_hump_A$());
業(yè)務(wù)接口實(shí)現(xiàn)類模版
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* $table_desc$業(yè)務(wù)實(shí)現(xiàn)
* Created by 創(chuàng)建人 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) {
// 入?yún)⑥D(zhuǎn)成對應(yīng)類型
CommonAssert.isNoEmptyObj(request, "請求參數(shù)不可空");
$table_name_hump_A$DTO dto = JSON.toJavaObject(request, $table_name_hump_A$DTO.class);
// 參數(shù)校驗(yàn)
$biz_check_required_params$
// 轉(zhuǎn)成do模型
$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, "創(chuàng)建失敗,請重試");
// 返回創(chuàng)建成功的ID數(shù)據(jù)
return new CommonResult(dataDo.get$primary_key_hump_A$());
}
@Override
public CommonResult modify(JSONObject request) {
// 入?yún)⑥D(zhuǎn)成對應(yīng)類型
CommonAssert.isNoEmptyObj(request, "請求參數(shù)不可空");
$table_name_hump_A$DTO dto = JSON.toJavaObject(request, $table_name_hump_A$DTO.class);
// 參數(shù)校驗(yàn)
$biz_check_required_params$
// 轉(zhuǎn)成do模型
$table_name_hump_A$DO dataDo = $table_name_hump_A$Converter.toDo(dto);
// 落庫
int count = $table_name_hump$DAO.update(dataDo);
CommonAssert.greaterThanZero(count, "修改失敗,請重試");
// 返回修改成功的ID數(shù)據(jù)
return new CommonResult(dataDo.get$primary_key_hump_A$());
}
@Override
public CommonResult pageQuery(JSONObject request) {
// 入?yún)⒒拘r?yàn)
CommonAssert.isNoEmptyObj(request, "請求參數(shù)不可空");
// 分頁信息校驗(yàn)
PaginationDO pagination = PaginationDO.setRequestOffsetAndRows(request);
CommonAssert.isNoEmptyObj(pagination, "分頁參數(shù) $pageIndex、$pageSize 不可空");
CommonAssert.isTrue(pagination.getPageSize() <= 100, "單次查詢條數(shù)不可超過100條");
// 取分頁列表數(shù)據(jù)
List<$table_name_hump_A$DO> dbResult = $table_name_hump$DAO.pageQuery(request);
// 取count數(shù)據(jù)
long count = $table_name_hump$DAO.pageQueryCount(request);
// 空返回
if (CollectionUtils.isEmpty(dbResult)){
return new CommonResult(new PaginationResult(null, request, count));
}
// 模型轉(zhuǎn)換
List<$table_name_hump_A$DTO> list = $table_name_hump_A$Converter.toDtoList(dbResult);
// 返回分頁結(jié)果
return new CommonResult(new PaginationResult(list, request, count));
}
@Override
public CommonResult queryById(JSONObject request) {
// 取入?yún)?/span>
CommonAssert.isNoEmptyObj(request, "請求參數(shù)不可空");
// 根據(jù)ID獲取數(shù)據(jù)
$primary_key_type_java$ $primary_key_hump$ = request.get$primary_key_type_java$("$primary_key_hump$");
CommonAssert.isNoEmptyObj($primary_key_hump$, "參數(shù)錯誤,無法執(zhí)行查詢");
$table_name_hump_A$DO dbResult = $table_name_hump$DAO.queryById($primary_key_hump$);
// 未查詢到結(jié)果,返回
if (null == dbResult){
return new CommonResult();
}
// 模型轉(zhuǎn)換
$table_name_hump_A$DTO result = $table_name_hump_A$Converter.toDto(dbResult);
// 返回結(jié)果對象
return new CommonResult(result);
}
}
成員代碼塊 必填項(xiàng)業(yè)務(wù)校驗(yàn)(biz_check_required_params)
CommonAssert.$java_type_adapter_assert_method$(dto.get$field_name_hump_A$(), "$field_comment$不可空");
Controller模版
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 創(chuàng)建人 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;
/**
* 創(chuàng)建
* @param request
* @return
*/
@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);
}
/**
* 修改
* @param request
* @return
*/
@RequestMapping(value = "modify.json", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object modify(@RequestBody JSONObject request){
return CommonTemplate.run(LOGGER, new CommonTemplate() {
@Override
protected Object business() {
return $table_name_hump$Service.modify(request);
}
}, request);
}
/**
* 分頁查詢
* @param request
* @return
*/
@RequestMapping(value = "pageQuery.json", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object pageQuery(@RequestBody JSONObject request){
return CommonTemplate.run(LOGGER, new CommonTemplate() {
@Override
protected Object business() {
return $table_name_hump$Service.pageQuery(request);
}
}, request);
}
/**
* 通過主鍵查詢
* @param request
* @return
*/
@RequestMapping(value = "queryById.json", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public Object queryById(@RequestBody JSONObject request){
return CommonTemplate.run(LOGGER, new CommonTemplate() {
@Override
protected Object business() {
return $table_name_hump$Service.queryById(request);
}
}, request);
}
}
動態(tài)參數(shù)
原始表名
$table_name$
-
表名駝峰首字母小寫 $table_name_hump$
-
表名駝峰首字母大寫 $table_name_hump_A$
-
表中文名 $table_desc$
用戶輸入的表中文名,不做任何處理。
-
數(shù)據(jù)庫引擎 $db_engine$
用戶輸入的表數(shù)據(jù)庫引擎,不做任何處理。
-
數(shù)據(jù)庫編碼 $db_encoded$
用戶輸入的表數(shù)據(jù)庫編碼,不做任何處理。
-
原始字段名 $field_name$
用戶輸入的表字段名,不做任何處理。
-
字段名駝峰首字母小寫 $field_name_hump$
用戶輸入的表字段名,經(jīng)過駝峰處理。例如輸入:order_number ,輸出:orderNumber
-
字段名駝峰首字母大寫 $field_name_hump_A$
用戶輸入的表字段名,經(jīng)過駝峰處理。例如輸入:order_number ,輸出:OrderNumber
-
字段說明 $field_comment$
用戶輸入的表字段說明,不做任何處理。
-
字段數(shù)據(jù)類型(對應(yīng)DB) $field_type_db$
用戶選擇的表字段類型,不做任何處理。
-
字段數(shù)據(jù)類型(對應(yīng)Java) $field_type_java$
用戶選擇的表字段類型,會自動匹配對應(yīng)的Java類型。例如輸入:VARCHAR(),輸出:String
-
主鍵字段名 $primary_key$
用戶選擇的主鍵字段,不做任何處理。例如用戶定義的主鍵是id,那么輸出就是:id
-
主鍵字段名駝峰首字母小寫 $primary_key_hump$
用戶選擇的主鍵字段,經(jīng)過駝峰處理。例如輸入:order_number ,輸出:orderNumber
-
主鍵字段名駝峰首字母大寫 $primary_key_hump_A$
用戶選擇的主鍵字段,經(jīng)過駝峰處理。例如輸入:order_number ,輸出:OrderNumber
-
主鍵字段數(shù)據(jù)類型(對應(yīng)Java) $primary_key_type_java$
用戶選擇的主鍵字段類型,會自動匹配對應(yīng)的Java類型。例如輸入:VARCHAR(),輸出:String
-
插入數(shù)據(jù)sql,字段名列表 $insert_field_name_list$
例如表中有三個字段:id(主鍵)、goods_name、price,輸出:goods_name,price 。會自動排除主鍵 不僅插入數(shù)據(jù)時可用,任何需要排除ID,然后使用英文逗號拼接表所有字段信息的地方,都可以使用它
-
插入數(shù)據(jù)sql,字段值列表 $insert_field_value_list$
例如表中有三個字段:id(主鍵)、goods_name、price,輸出:#{goodsName},#{price} 。會自動排除主鍵 不僅插入數(shù)據(jù)時可用,任何需要排除ID,然后使用英文逗號拼接表所有字段信息的地方,都可以使用它
-
修改數(shù)據(jù)sql,字段名列表 $update_field_list$
例如表中有三個字段:id(主鍵)、goods_name、price 輸出(會自動換行,會攜帶以下縮進(jìn),會自動排除主鍵):
goods_name = #{goodsName},
price = #{price}
查詢數(shù)據(jù)sql,字段名列表
$select_field_list$
例如表中有三個字段:id(主鍵)、goods_name、price,輸出:id,goods_name,price 。帶主鍵
-
whele字段條件sql,字段名列表 $where_field_list$
例如表中有三個字段:id(主鍵)、goods_name、price, 輸出(會自動換行,會攜帶以下縮進(jìn)):
<if test="id != null">
AND id = #{id}
</if>
<if test="goodsName != null">
AND goods_name = #{goodsName}
</if>
<if test="price != null">
AND price = #{price}
</if>
-
創(chuàng)建表-表字段列表 $create_table_field_list$
例如表中有三個字段:id(自增主鍵)、goods_name、price 輸出(會自動換行,會攜帶以下縮進(jìn)):
`id` INT(11) NOT NULL AUTO_INCREMENT,
`goods_name` VARCHAR(128) NOT NULL DEFAULT 'NULL',
`price` DECIMAL(10,2) NOT NULL DEFAULT 'NULL'
-
當(dāng)前時間 $current_time$
自動獲取當(dāng)前時間,格式:yyyy-MM-DD hh:mm:ss,示例值:2023-02-05 17:31:18
-
自動根據(jù)數(shù)據(jù)類型,匹配斷言方法 $java_type_adapter_assert_method$
對于Java數(shù)據(jù)類型等于String的字段,使用isNoBlankStr方法,其他的類型都使用isNoEmptyObj方法 這是一個定制化很高的動態(tài)參數(shù),可忽略它。
動態(tài)代碼塊
動態(tài)代碼塊由用戶自行定義,代碼塊中也可以設(shè)置動態(tài)參數(shù),目前僅提供4種明確的動態(tài)代碼塊
-
成員變量列表 $member_param_list$
例如表中有三個字段:id(主鍵)、goods_name、price
假設(shè)用戶定義了如下代碼塊內(nèi)容:
/** $field_comment$ */
private $field_type_java$ $field_name_hump$;
輸出(會自動根據(jù)字段數(shù)量,累加輸出自定義代碼塊內(nèi)容):
/** id */
private Integer id;
/** 商品名稱 */
private String goodsName;
/** 商品價格 */
private String price;
GetSet方法列表
$get_set_method_list$
例如表中有三個字段:id(主鍵)、goods_name、price
假設(shè)用戶定義了如下代碼塊內(nèi)容:
public $field_type_java$ get$field_name_hump_A$() {
return $field_name_hump$;
}
public void set$field_name_hump_A$($field_type_java$ $field_name_hump$) {
this.$field_name_hump$ = $field_name_hump$;
}
輸出(會自動根據(jù)字段數(shù)量,累加輸出自定義代碼塊內(nèi)容):
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
-
模型轉(zhuǎn)換器參數(shù)列表 $converter_source_to_target_params_list$
例如表中有三個字段:id(主鍵)、goods_name、price
假設(shè)用戶定義了如下代碼塊內(nèi)容:
target.set$field_name_hump_A$(source.get$field_name_hump_A$());
輸出(會自動根據(jù)字段數(shù)量,累加輸出自定義代碼塊內(nèi)容):
target.setId(source.getId());
target.setGoodsName(source.getGoodsName());
target.setPrice(source.getPrice());
必填項(xiàng)業(yè)務(wù)校驗(yàn)
$biz_check_required_params$
例如表中有三個字段:id(主鍵)、goods_name、price
假設(shè)用戶定義了如下代碼塊內(nèi)容:
CommonAssert.$java_type_adapter_assert_method$(dto.get$field_name_hump_A$(), "$field_comment$不可空");
輸出(會自動根據(jù)字段數(shù)量,累加輸出自定義代碼塊內(nèi)容):
CommonAssert.isNoBlankStr(dto.getGoodsName(), "goodsName不可空");
CommonAssert.isNoBlankStr(dto.getPrice(), "price不可空");
這個工具已經(jīng)開源,可以移步:
https://github.com/GooseCoding/utilsbox
感謝閱讀,希望對你有所幫助 :) 來源:juejin.cn/post/7200552990737432633
最后,關(guān)注公眾號互聯(lián)網(wǎng)架構(gòu)師,在后臺回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。
正文結(jié)束
推薦閱讀 ↓↓↓
正文結(jié)束
