Quellcode durchsuchen

Merge pull request #75 from hs-web/3.0.0-RC

3.0.0 rc
zhōuhào vor 7 Jahren
Ursprung
Commit
0642a33859

+ 5 - 0
hsweb-commons/hsweb-commons-dao/README.md

@@ -0,0 +1,5 @@
+# 通用DAO实现
+
+支持动态条件的通用CRUD实现
+
+⚠️注意:目前仅提供了[mybatis](hsweb-commons-dao-mybatis)实现.

+ 219 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/README.md

@@ -0,0 +1,219 @@
+# 基于mybatis的通用crud实现
+
+使用myabtis和easy-orm对`hsweb-commons-dao-api`进行了实现,提供动态条件对crud支持.
+
+# 使用
+在pom.xml中引入:
+
+```xml
+<dependency>
+    <groupId>org.hswebframework.web</groupId>
+    <artifactId>hsweb-commons-dao-mybatis</artifactId>
+    <version>${hsweb.framework.version}</version>
+</dependency>
+```
+
+# 配置
+application.yml
+
+```yaml
+mybatis:
+  # 扫描myabtis mapper xml的路径
+  mapper-locations: classpath*:com/company/app/**/*Mapper.xml
+  # 这里需要配置扫描枚举,才能支持对实现了EnumDict接口的枚举进行序列化和反序列化
+  type-handlers-package: com.company.app.enums 
+  # 是否开启动态数据源,开启后才能支持在同一个dao中切换数据源
+  dynamic-datasource: false
+  # 排除扫描xml配置,用于需要拓展无法修改的mapper xml时,通过此配置不加载对应的xml,然后通过mapper-locations配置加载新的xml.
+  mapper-location-excludes: classpath*:com/company/app/x/y/*Mapper.xml
+```
+
+# 使用通用Mapper XMl
+
+目前仅支持xml的方式,例如:
+
+```xml
+
+<?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="org.hswebframework.web.dao.crud.TestDao">
+
+    <resultMap id="TestResultMap" type="org.hswebframework.web.dao.crud.TestEntity">
+        <!--这里需要声明id-->
+        <id property="id" column="id" javaType="Long" jdbcType="INTEGER"/>
+        <!--如果没有使用jpa注解,需要在这里添加配置,因为动态生成sql的时候是根据resultMap中的字段进行配置的-->
+    </resultMap>
+
+   <!--另外一个resultMap,用于演示表关联-->
+    <resultMap id="TestNestResultMap" type="org.hswebframework.web.dao.crud.TestEntity">
+        <id property="id" column="id" javaType="Long" jdbcType="INTEGER"/>
+        <!--jpa目前不支持表关联的解析,所以要在这里定义另外一个关联实体的全部信息,其中,column=关联表别名.列名-->
+        <result property="nest.name" column="nest_table.name" javaType="String" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <!--用于动态生成sql所需的配置-->
+    <sql id="config">
+        <!--声明2个在生成动态sql时需要用到的变量-->
+        <!--注意value里的单引号,因为value属性为一个ognl表达式-->
+        <bind name="resultMapId" value="'TestResultMap'"/> 
+        <bind name="tableName" value="'h_test'"/>
+    </sql>
+
+    <!--注意:keyColumn,keyProperty,useGeneratedKeys,只有在数据库生成id的时候才需要配置-->
+    <insert id="insert" keyColumn="id" keyProperty="id" useGeneratedKeys="true" parameterType="org.hswebframework.web.dao.crud.TestEntity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildInsertSql"/>
+    </insert>
+
+    <update id="update" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildUpdateSql"/>
+    </update>
+
+    <select id="query" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="TestResultMap">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildSelectSql"/>
+    </select>
+
+    <select id="count" parameterType="org.hswebframework.web.commons.entity.Entity" resultType="int">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildTotalSql"/>
+    </select>
+
+     <!--表关联的查询-->
+    <select id="queryNest" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="TestNestResultMap">
+        <bind name="tableName" value="'h_test'"/>
+        <bind name="resultMapId" value="'TestNestResultMap'"/>
+        select
+        <include refid="BasicMapper.buildSelectField"/>
+        from h_test <!--注意h_nest_table的别名:nest_table-->
+        left join h_nest_table nest_table on nest_table.id=h_test.id
+        <where>
+            <include refid="BasicMapper.buildWhere"/>
+        </where>
+        <include refid="BasicMapper.buildSortField"/>
+    </select>
+
+    <select id="countNest" parameterType="org.hswebframework.web.commons.entity.Entity" resultType="int">
+        <include refid="config"/>
+        select
+        count(1)
+        from h_test
+        left join h_nest_table nest_table on nest_table.id=h_test.id
+        <where>
+            <include refid="BasicMapper.buildWhere"/>
+        </where>
+    </select>
+
+</mapper>
+
+```
+
+⚠️注意:query(count),update,delete方法的参数目前仅实现了:
+
+`org.hswebframework.web.commons.entity.param.QueryParamEntity`
+
+`org.hswebframework.web.commons.entity.param.UpdateParamEntity`
+
+`org.hswebframework.web.commons.entity.param.DeleteParamEntity`
+
+因此在实际调用都时候,目前只能接收对应以上参数.
+但是在接口中仍然使用`org.hswebframework.web.commons.entity.Entity`作为参数,用于预留给以后提供更多都参数实现.
+
+# 动态条件
+此模块使用hsweb-easyorm项目来进行动态SQL条件的生成,主要是通过:在上述的`**ParamEntity`类中的属性 `List<Term> terms;`
+进行处理,`Term`为一个SQL条件,例如一个简单的嵌套条件:
+```text
+    [{
+      column:"name",
+      termType:"eq", #SQL条件类型 =
+      value:"张三",
+      terms:[
+        {
+          column:"address",
+          termType:"like", //SQL条件类型 like
+          value:"北京%"
+         },
+         {
+           column:"address",
+           type:"or" //和前面的条件成or关系,如果不指定,默认为and
+           termType:"like", //SQL条件类型 like
+           value:"上海%"
+          }
+        ]
+      }]
+```
+对应的sql条件为: where name = ? and (address like ? or address lke ?)
+
+条件构造方式看上去过于复杂? 可以使用DSL方式的构建工具类:`org.hswebframework.ezorm.core.dsl.Query`来进行构建.
+在[hsweb-commons-service-api](../../hsweb-commons-service/hsweb-commons-service-api)模块也会提供便捷的条件创建方式.
+
+如果参数来自客户端请求,可封装一个通用的js进行构建, 你可以在前端放心的构建参数,所有的条件都使用参数化预编译的方式拼接SQL,不存在SQL注入问题.
+
+## 默认支持的动态条件列表
+| termType       | 对应SQL          |   说明 |
+| ------------- |:-------------:| ----|
+|eq|=?| 等于|
+|not |!=?| 不等于|
+|gt|>?| 大于|
+|gte|>= ?| 大于等于|
+|lt|< ?| 小于|
+|lte| <= ?|  小于等于|
+|like|like ?| 模糊匹配,如果需要统配符,请自行拼接value,如: value+"%" |
+|nlike|not like ?| 同like |
+|in|in(?,?)| value 可使用半角逗号(,)分隔,或者数组或者`Collection`接口的实现 |
+|nin|not in(?,?)| value 可使用半角逗号(,)分隔,或者数组或者`Collection`接口的实现 |
+|isnull| is null | value为任意不为空的值即可 |
+|notnull| not null | value为任意不为空的值即可 |
+|empty| ='' | value为任意不为空的值即可 |
+|nempty| !='' | value为任意不为空的值即可 |
+|bwt|between ? and ? | value 可使用半角逗号(,)分隔,或者使用数组或者Collection接口的实现|
+|nbwt|not between ? and ? | value 可使用半角逗号(,)分隔,或者使用数组或者Collection接口的实现|
+
+## 拓展动态条件
+在某些需要自定义查询条件的场景,比如关联条件,可通过实现`SqlTermCustomer`接口并注入到spring来进行自定义SQL条件的拼接,
+例如:
+```java
+//AbstractSqlTermCustomer提供了一些便利的方法
+@org.springframework.stereotype.Component
+public class MyTerm extends AbstractSqlTermCustomer{
+
+    @Override
+    public String getTermType() {
+        //对应Term参数中的属性termType
+        return "my-term";
+    }
+
+    @Override
+    public Dialect[] forDialect() {
+        //对特定对数据库类型生效,返回null时对全部支持对数据库类型生效
+        return null;
+    }
+
+
+    @Override
+    public SqlAppender accept(String wherePrefix, Term term, RDBColumnMetaData column, String tableAlias) {
+        //当传入了my-term条件对时候,会调用此方法进行拼接
+        //对传入对参数进行转换,此步骤为必须的
+       ChangedTermValue termValue =createChangedValue(term);
+        
+       //转换参数,将参数转为集合,以支持in查询. 
+       List<Object> idList = BoostTermTypeMapper.convertList(column, termValue.getOld());
+        
+       SqlAppender appender=  new SqlAppender();
+      
+       appender.add(createColumnName(column,tableAlias),"in (select id from my_table where t_id");
+        
+        //根据参数的数量,构造对应的=或者in条件
+       Object newValue= appendCondition(idList,wherePrefix,appender);
+        
+       appender.add(")");
+       //设置新的值到条件中
+       termValue.setValue(newValue);
+        
+        return appender;
+    }
+}
+```
+
+使用: 在查询的时候,将`Term`的`termType`属性值设置为`my-term`即可.

+ 1 - 1
hsweb-system/hsweb-system-organizational/README.md

@@ -6,7 +6,7 @@
 `hsweb-system-organizational-local`模块中提供了一些自定义的查询条件,用于对组织机构关联查询.可以在动态查询中
 进行使用,例如:
 
-```xml
+```java
 
 //查询orgId为1234的机构以及其所有子机构的数据
 createQuery().where("orgId","org-child-in","1234").list();