瀏覽代碼

jdbc 说明文档

zuy 1 年之前
父節點
當前提交
6bd6827749
共有 2 個文件被更改,包括 367 次插入0 次删除
  1. 1 0
      car-wash-admin/src/main/java/com/kym/admin/utils/CommJdbcCodeGenerator.java
  2. 366 0
      jdbc.md

+ 1 - 0
car-wash-admin/src/main/java/com/kym/admin/utils/CommJdbcCodeGenerator.java

@@ -54,6 +54,7 @@ public class CommJdbcCodeGenerator {
 
 
         List<Map<String, String>> pathList = new ArrayList<>();
+        //修改代码输出路径
         pathList.add(ImmutableMap.of("vm", "Controller.java.vm", "output", "/home/zuy/02.code/wash/car-wash-admin/src/main/java/com/kym/admin/controller"));
         pathList.add(ImmutableMap.of("vm", "Service.java.vm", "output", "/home/zuy/02.code/wash/car-wash-service/src/main/java/com/kym/service/admin/"));
         pathList.add(ImmutableMap.of("vm", "ServiceImpl.java.vm", "output", "/home/zuy/02.code/wash/car-wash-service/src/main/java/com/kym/service/admin/impl"));

+ 366 - 0
jdbc.md

@@ -0,0 +1,366 @@
+## Comm-JDBC 使用指引
+
+### 1. 说明
+
+    a.本框架基于springboot jdbcTemplate二次封装,支持事务,分页,批量、函数、存储过程操作等,支持MySQL、PostgreSQL等多方言关系数据的读写操作。
+    b.数据核心pojo类一一对应数据库表,使用自定义的注解解析器动态生成SQL,相较于mybatis支持pojo类配置封装类型如List、Set、Map、自定义类的持久化和序列化反序列化操作,无须配置类型处理器,无须配置mapper.xml。
+    c.除了pojo类注解方式,也兼容自定义SQL读写操作,此时封装类需自行处理(适用于复杂SQL)。
+    d.代码生成类 /wash/car-wash-admin/src/main/java/com/kym/admin/utils/CommJdbcCodeGenerator.java
+### 2. 基类
+
+    DbHandler:所有DAO类继承该类,提供基础CRUD操作,支持事务,分页,批量操作等。
+    BasicQuery:查询封装基类(第一种,适用于暴露前端接口参数定义,默认分页30),预封装查询参数,动态生成关联查询条件、排序SQL语句。
+    OBuilder:查询封装类(第二种,适用于后端业务查询),按需查询,类似mybatisplus语法。
+
+### 3. 使用
+
+以知识库t_org_doc表为例,介绍如何使用本框架进行CRUD操作。
+#### 3.1 定义实体类(OrgDoc)
+```java
+package com.png.entity.po.org;
+
+import com.png.entity.bo.AccessStrategy;
+import com.png.entity.po.user.User;
+import com.png.entity.vo.SimpleVo;
+import com.png.entity.vo.SimpleVo.SimpleAttachVo;
+import com.png.jdbc.BasicQuery;
+import com.png.jdbc.annotations.DBF;
+import com.png.jdbc.annotations.Entity;
+import com.png.jdbc.annotations.FK;
+import com.png.jdbc.annotations.OP;
+import com.png.jdbc.annotations.One;
+import com.png.jdbc.annotations.QE;
+import com.png.jdbc.annotations.QF;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * 知识库
+ *
+ * @author yaop
+ * @date 2024-02-03T10:44:52.780
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Entity(clz = OrgDoc.class, comment = "知识库")
+public class OrgDoc implements Serializable {
+
+    public static final int STATUS_拟稿中= 1;
+    public static final int STATUS_已发布= 2;
+
+    @DBF(comment = "ID")
+    private long id;
+    @DBF(comment = "组织")
+    private long oid;
+    @DBF(comment = "应用")
+    private long appletId;
+
+    @NotEmpty(message = "名称不能为空")
+    @DBF(comment = "名称", max = 128)
+    private String name;
+
+    @DBF(comment = "摘要", max = 512)
+    private String digest;
+    @DBF(comment = "文章目录")
+    private List<OrgDocOutline> outlineList;
+    @DBF(comment = "是否目录")
+    private boolean directory;
+    @DBF(comment = "父级目录")
+    private long pid;
+    @DBF(comment = "所在目录结构")
+    private List<String> pathList;
+    @DBF(comment = "状态")
+    private int status;
+    @DBF(comment = "排序权重")
+    private int weight;
+
+    @DBF(comment = "附件清单")
+    private List<Long> attachIdList;
+    @DBF(comment = "附件清单")
+    private List<SimpleAttachVo> attachList;
+
+    @DBF(comment = "是否删除")
+    private boolean deleted;
+
+
+    @DBF(comment = "是否开启访问控制")
+    private boolean accessAvailable;
+
+    @DBF(comment = "访问策略")
+    private AccessStrategy accessStrategy;
+
+
+    @DBF(comment = "创建时间")
+    private Date createAt;
+    @FK(clz = User.class)
+    @DBF(comment = "创建人")
+    private long createBy;
+    @DBF(comment = "更新时间")
+    private Date updateAt;
+
+    @FK(clz = User.class)
+    @DBF(comment = "更新人")
+    private long updateBy;
+    @DBF(comment = "源文章")
+    private long sid;
+    @DBF(comment = "是否最新版本")
+    private boolean latest;
+    @DBF(comment = "版本号")
+    private int version;
+    //region 版本相关
+
+    //endregion
+
+    @Data
+    @EqualsAndHashCode(callSuper = true)
+    public static class OrgDocInfo extends OrgDoc {
+        @One(mkf = "createBy", tf = "name", comment = "创建人")
+        private String createName;
+
+        //扩展类字段,查询Info扩展类时自动生成SQL
+        @One(mkf = "updateBy", tf = "name", comment = "更新人")
+        private String updateName;
+
+        //扩展类字段,无注解不会持久化
+        private String content;
+    }
+
+    /**
+     * 富文本目录结构
+     */
+    @Data
+    public static class OrgDocOutline {
+        private String id;
+        /**
+         * 目录名称(或内容)
+         */
+        private String text;
+        /**
+         * level: 目录级别,值是 1 ~ 6,对应的 html 标签是 h1 ~ h6
+         */
+        private int level;
+        /**
+         * 目录节点所在文档位置
+         */
+        private int pos;
+        /**
+         * 目录节点的内容大小
+         */
+        private int size;
+    }
+
+    /**
+     *查询实体类,字段为封装类型,框架根据非空值生成SQL
+     */
+    @Data
+    @EqualsAndHashCode(callSuper = true)
+    @QE(clz = OrgDocInfo.class)
+    public static class OrgDocBasicQuery extends BasicQuery {
+        private Long id;
+        private Long orgId;
+        private Long appletId;
+        private String name;
+        private String digest;
+        private Long pid;
+        private Integer status;
+        private String attachIdList;
+        private String attachList;
+        private String userIdList;
+        private String userList;
+        private String roleList;
+        private String roleIdList;
+        private Long createBy;
+        private Long updateBy;
+        private Long sid;
+        private Boolean latest;
+        private Integer version;
+
+        //region date query
+        @QF(op = OP.GTE, tf = "createAt")
+        private Date createAtStart;
+        @QF(op = OP.LTE, tf = "createAt")
+        private Date createAtEnd;
+        @QF(op = OP.GTE, tf = "updateAt")
+        private Date updateAtStart;
+        @QF(op = OP.LTE, tf = "updateAt")
+        private Date updateAtEnd;
+        //endregion
+        
+        //json数组查询(第一种,自定义sql片段)
+        @QF(sql="json_contains(l.attach_id_list,?) ")
+        private Long attachId;
+
+        //json数据查询(第二种)
+        @QF(op = OP.JIN, tf = "attachIdList")
+        private Long attachId;
+
+        //关联查询
+        @QF(tf = "name",pkf = "createBy")
+        private String createName;
+
+
+        //region sort query  1-升序  2-降序
+        private Integer idSort;
+        private Integer orgIdSort;
+        private Integer appletIdSort;
+        private Integer pidSort;
+        private Integer statusSort;
+        private Integer createAtSort;
+        private Integer createBySort;
+        private Integer updateAtSort;
+        private Integer updateBySort;
+        //endregion
+    }
+}
+```
+
+#### 3.2 定义持久类(OrgDocDAO)
+```java
+package com.png.dao.org;
+
+import com.png.JacksonUtil;
+import com.png.dao.DbHandler;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+
+@Component("orgDocDAO")
+public class OrgDocDAO extends DbHandler {
+
+    /**
+     * 更新旧版本标识
+     * @param sid
+     * @param latest
+     */
+    public void updateVersionLatest(long sid, boolean latest) {
+        update("update t_org_doc set latest = ? where sid = ?", latest, sid);
+    }
+
+
+    /**
+     * 更新旧版本的文档路径
+     * @param sid
+     * @param pathList
+     */
+    public void updateOldVersionPath(long sid, List<String> pathList) {
+        update("update t_org_doc set path_list=? where sid =?", JacksonUtil.toJSONString(pathList),sid);
+
+    }
+}
+
+```
+#### 3.3  编写业务类(OrgDocService)
+```java
+package com.png.service.org;
+
+
+/**
+ * 知识库业务类
+ *
+ * @author yaop
+ * @date 2024-02-03T10:44:52.780
+ */
+@Service("orgDocService")
+public class OrgDocService extends IService {
+
+    @Resource
+    private OrgDocDAO orgDocDAO;
+
+}
+```
+
+##### 3.3.1 插入-insert
+```java
+    OrgDoc orgDoc = new OrgDoc();
+    orgDoc.setSid(orgDoc.getId());
+        orgDoc.setLatest(true);
+    orgDoc.setVersion(1);
+    if (orgDoc.getPid() == 0) {
+        orgDoc.setPathList(List.of("/"));
+        } else {
+    OrgDoc parent = orgDocDAO.selectOneExist(OrgDoc.class, orgDoc.getPid());
+        parent.getPathList().add(parent.getName());
+        //封装类型字段,除业务处理外不做其他操作
+        orgDoc.setPathList(parent.getPathList());
+        }
+//插入数据库,有ID返回
+long id = orgDocDAO.insert(orgDoc);
+//插入数据库,无ID返回
+    orgDocDAO.insertOnly(orgDoc);
+//插入数据库,有ID返回,跳过status、digest字段
+    orgDocDAO.insertSelective(orgDoc,"status","digest");
+//插入数据库,无ID返回,跳过status、digest字段
+    orgDocDAO.insertSelectiveOnly(orgDoc,"status","digest");
+//批量插入
+    orgDocDAO.insertBatch(orgDocs);
+//批量插入 ,仅插入id name字段 
+    orgDocDAO.insertBatch(List.of("name","id"),orgDocs);
+        //批量插入,自定义sql方式
+    orgDocDAO.insertBatch("insert into t_org_doc (id,name) values (?,?)",orgDocs);
+```
+
+##### 3.3.2 删除-delete
+```java
+    //删除ID为1的知识库记录
+    orgDocDAO.delete(OrgDoc.class,1);
+//删除状态有效且创建时间大于‘2024-09-01’的知识库记录,builder方式条件构造
+    orgDocDAO. delete(User.class,OBuilder.build().eq(OrgDoc::getStatus,Consts.STATUS_有效).gt(OrgDoc::getCreateAt,date));
+```
+
+
+##### 3.3.3 修改-update
+```java
+    //更新ID为1的知识库记录的名称为wiki1111
+    OrgDoc orgDoc = new OrgDoc();
+    orgDoc.setId(1);
+    orgDoc.setName("wiki11111");
+    orgDocDAO.update(orgDoc);
+//更新ID为1的知识库记录
+    orgDocDAO. update(orgDoc,OBuilder.build().eq(OrgDoc::getID,1));
+  //更新ID为1的知识库记录
+    orgDocDAO. update("UPDATE t_org_doc set name = ?  where id =? ","wiki111",1)); 
+//批量更新,默认where条件为id
+    orgDocDAO. updateBatch(List.of("name"),orgDocs);
+    //批量更新,sql方式
+    orgDocDAO. updateBatch("UPDATE t_org_doc set name = ?  where id =?  and status =? ",orgDocs);
+```
+
+##### 3.3.4  查询-select
+
+```java
+//查询ID为1的知识库记录,无关联扩展字段
+OrgDoc orgDoc = orgDocDAO.selectOne(OrgDoc.class, OBuilder.build().eq(OrgDoc::getID, 1));
+//查询ID为1的知识库记录,自动关联外键字段
+OrgDocInfo orgDoc = orgDocDAO.selectOne(OrgDocInfo.class, OBuilder.build().eq(OrgDoc::getID, 1));
+//查询ID为1的知识库记录,自动关联外键字段并校验记录是否存在,不存在时抛出异常IllegalArgumentException
+OrgDocInfo orgDoc = orgDocDAO.selectOneExist(OrgDocInfo.class, OBuilder.build().eq(OrgDoc::getID, 1));
+//查询ID为1的知识库记录, 无关联外键字段并校验记录是否存在,不存在时抛出异常IllegalArgumentException
+OrgDoc orgDoc = orgDocDAO.selectOneExist(OrgDoc.class, 1);
+//查询ID为1的知识库记录,自动关联外键字段,且仅查询id name attachList字段(封装类自动处理)
+OrgDocInfo orgDoc = orgDocDAO.selectOne(OrgDocInfo.class, OBuilder.build().eq(OrgDoc::getID, 1), List.of("id","name","attachList"));
+//查询ID为1的知识库记录,自动关联外键字段,且查询i排除d name attachList字段
+OrgDocQuery query = new OrgDocQuery();
+query.setId(1);
+OrgDocInfo orgDoc = orgDocDAO.selectOneExclude(query, List.of("id","name","attachList"));
+
+//查询I状态有效的的知识库记录列表,自动关联外键字段(第一种,builder构造查询条件)
+List<OrgDocInfo> orgDocs = orgDocDAO.selectList(OrgDocInfo.class, OBuilder.build().eq(OrgDoc::getStatus, Consts.STATUS_有效));
+//查询I状态有效的的知识库记录列表,自动关联外键字段且查询i排除d name attachList字段(第二种,query实体类查询)
+OrgDocQuery query = new OrgDocQuery();
+query.setStatus(Consts.STATUS_有效);
+OrgDocInfo orgDoc = orgDocDAO.selectListExclude(query, List.of("id","name","attachList"));
+//查询I状态有效的的知识库记录列表 (第三种,自定义sql语句)
+List<OrgDocInfo> orgDocs = orgDocDAO.selectList("select id,name from t_org_doc",data->{
+    OrgDocInfo info = new OrgDocInfo();
+    info.setId(data.get("id"));
+    return info;
+},  Consts.STATUS_有效));
+
+```