浏览代码

增加对mybatis association标签对支持,增加对jpa注解CollectionTable对支持,增加对boolean与数字转换对支持

zhou-hao 5 年之前
父节点
当前提交
75e07d8534

+ 89 - 45
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/main/java/org/hswebframework/web/dao/mybatis/builder/EasyOrmSqlBuilder.java

@@ -38,9 +38,11 @@ import org.hswebframework.ezorm.rdb.render.dialect.*;
 import org.hswebframework.ezorm.rdb.render.support.simple.CommonSqlRender;
 import org.hswebframework.ezorm.rdb.render.support.simple.SimpleWhereSqlBuilder;
 import org.hswebframework.web.BusinessException;
+import org.hswebframework.web.bean.FastBeanCopier;
 import org.hswebframework.web.commons.entity.Entity;
 import org.hswebframework.web.commons.entity.factory.EntityFactory;
 import org.hswebframework.web.dao.mybatis.builder.jpa.JpaAnnotationParser;
+import org.hswebframework.web.dao.mybatis.handler.NumberBooleanTypeHandler;
 import org.hswebframework.web.dao.mybatis.plgins.pager.Pager;
 import org.hswebframework.web.dao.mybatis.MybatisUtils;
 import org.hswebframework.utils.StringUtils;
@@ -145,6 +147,50 @@ public class EasyOrmSqlBuilder {
 
     }
 
+    private List<RDBColumnMetaData> createColumn(String prefix, String columnName, ResultMapping resultMapping) {
+        List<RDBColumnMetaData> metaData = new ArrayList<>();
+        if (resultMapping.getNestedQueryId() == null) {
+
+            if (resultMapping.getNestedResultMapId() != null) {
+                ResultMap nests = MybatisUtils.getResultMap(resultMapping.getNestedResultMapId());
+                List<ResultMapping> resultMappings = new ArrayList<>(nests.getResultMappings());
+                resultMappings.addAll(nests.getIdResultMappings());
+                for (ResultMapping mapping : resultMappings) {
+                    metaData.addAll(createColumn(resultMapping.getProperty(),
+                            org.springframework.util.StringUtils.hasText(resultMapping.getColumn())
+                                    ? resultMapping.getColumn()
+                                    : resultMapping.getProperty(),
+                            mapping));
+                }
+                return metaData;
+            }
+
+            JDBCType jdbcType = JDBCType.VARCHAR;
+            try {
+                jdbcType = JDBCType.valueOf(resultMapping.getJdbcType().name());
+            } catch (Exception e) {
+                log.warn("can not parse jdbcType:{}", resultMapping.getJdbcType());
+            }
+            RDBColumnMetaData column = new RDBColumnMetaData();
+            column.setJdbcType(jdbcType);
+            column.setName(org.springframework.util.StringUtils.hasText(columnName)
+                    ? columnName.concat(".").concat(resultMapping.getColumn()) : resultMapping.getColumn());
+
+            if (resultMapping.getTypeHandler() != null) {
+                column.setProperty("typeHandler", resultMapping.getTypeHandler().getClass().getName());
+            }
+            if (!StringUtils.isNullOrEmpty(resultMapping.getProperty())) {
+                column.setAlias(org.springframework.util.StringUtils.hasText(prefix)
+                        ? prefix.concat(".").concat(resultMapping.getProperty()) : resultMapping.getProperty());
+
+            }
+            column.setJavaType(resultMapping.getJavaType());
+            column.setProperty("resultMapping", resultMapping);
+            metaData.add(column);
+        }
+        return metaData;
+    }
+
     protected RDBTableMetaData createMeta(String tableName, String resultMapId) {
 //        tableName = getRealTableName(tableName);
         RDBDatabaseMetaData active = getActiveDatabase();
@@ -169,40 +215,11 @@ public class EasyOrmSqlBuilder {
 
         List<ResultMapping> resultMappings = new ArrayList<>(resultMaps.getResultMappings());
         resultMappings.addAll(resultMaps.getIdResultMappings());
-        for (ResultMapping resultMapping : resultMappings) {
-            if (resultMapping.getNestedQueryId() == null) {
-                RDBColumnMetaData column = new RDBColumnMetaData();
-                column.setJdbcType(JDBCType.valueOf(resultMapping.getJdbcType().name()));
-                column.setName(resultMapping.getColumn());
-                if (resultMapping.getTypeHandler() != null) {
-                    column.setProperty("typeHandler", resultMapping.getTypeHandler().getClass().getName());
-                }
-                if (!StringUtils.isNullOrEmpty(resultMapping.getProperty())) {
-                    column.setAlias(resultMapping.getProperty());
-                }
-                column.setJavaType(resultMapping.getJavaType());
-                column.setProperty("resultMapping", resultMapping);
-                //时间
-                if (column.getJdbcType() == JDBCType.DATE || column.getJdbcType() == JDBCType.TIMESTAMP) {
-                    ValueConverter dateConvert = new DateTimeConverter("yyyy-MM-dd HH:mm:ss", column.getJavaType()) {
-                        @Override
-                        public Object getData(Object value) {
-                            if (value instanceof Number) {
-                                return new Date(((Number) value).longValue());
-                            }
-                            return super.getData(value);
-                        }
-                    };
-                    column.setValueConverter(dateConvert);
-                } else if (column.getJavaType() == boolean.class || column.getJavaType() == Boolean.class) {
-                    column.setValueConverter(new BooleanValueConverter(column.getJdbcType()));
-                } else if (TypeUtils.isNumberType(column)) { //数字
-                    //数字
-                    column.setValueConverter(new NumberValueConverter(column.getJavaType()));
-                }
-                rdbTableMetaData.addColumn(column);
-            }
-        }
+
+        resultMappings.stream()
+                .map(mapping -> this.createColumn(null, null, mapping))
+                .flatMap(Collection::stream)
+                .forEach(rdbTableMetaData::addColumn);
 
         if (useJpa) {
             Class type = entityFactory == null ? resultMaps.getType() : entityFactory.getInstanceType(resultMaps.getType());
@@ -217,6 +234,27 @@ public class EasyOrmSqlBuilder {
                 }
             }
         }
+        for (RDBColumnMetaData column : rdbTableMetaData.getColumns()) {
+            //时间
+            if (column.getJdbcType() == JDBCType.DATE || column.getJdbcType() == JDBCType.TIMESTAMP) {
+                ValueConverter dateConvert = new DateTimeConverter("yyyy-MM-dd HH:mm:ss", column.getJavaType()) {
+                    @Override
+                    public Object getData(Object value) {
+                        if (value instanceof Number) {
+                            return new Date(((Number) value).longValue());
+                        }
+                        return super.getData(value);
+                    }
+                };
+                column.setValueConverter(dateConvert);
+            } else if (column.getJavaType() == boolean.class || column.getJavaType() == Boolean.class) {
+                column.setValueConverter(new BooleanValueConverter(column.getJdbcType()));
+                column.setProperty("typeHandler", NumberBooleanTypeHandler.class.getName());
+            } else if (TypeUtils.isNumberType(column)) { //数字
+                //数字
+                column.setValueConverter(new NumberValueConverter(column.getJavaType()));
+            }
+        }
         cache.put(cacheKey, rdbTableMetaData);
         return rdbTableMetaData;
     }
@@ -230,6 +268,9 @@ public class EasyOrmSqlBuilder {
         CommonSqlRender render = (CommonSqlRender) databaseMetaDate.getRenderer(SqlRender.TYPE.SELECT);
         List<CommonSqlRender.OperationColumn> columns = render.parseOperationField(tableMetaData, param);
         SqlAppender appender = new SqlAppender();
+        Object data = param.getData();
+        Map<String, Object> mapData = FastBeanCopier.copy(data, HashMap::new);
+
         columns.forEach(column -> {
 
             RDBColumnMetaData columnMetaData = column.getRDBColumnMetaData();
@@ -242,21 +283,24 @@ public class EasyOrmSqlBuilder {
             if (columnMetaData.getProperty("read-only").isTrue()) {
                 return;
             }
-            Object value;
-            try {
-                value = propertyUtils.getProperty(param.getData(), columnMetaData.getAlias());
-                if (value == null) {
-                    return;
-                }
-            } catch (Exception e) {
+            Object value = mapData.get(columnMetaData.getAlias());
+
+            if (value == null) {
                 return;
             }
+
             if (value instanceof Sql) {
-                appender.add(",", encodeColumn(dialect, columnMetaData.getName())
-                        , "=", ((Sql) value).getSql());
+                appender.add(",", encodeColumn(dialect, columnMetaData.getName()), "=", ((Sql) value).getSql());
             } else {
-                String typeHandler = columnMetaData.getProperty("typeHandler")
-                        .getValue();
+                value = columnMetaData.getValueConverter().getData(value);
+
+                if (columnMetaData.getOptionConverter() != null) {
+                    value = columnMetaData.getOptionConverter().converterData(value);
+                }
+
+                mapData.put(columnMetaData.getAlias(), value);
+
+                String typeHandler = columnMetaData.getProperty("typeHandler").getValue();
 
                 appender.add(",", encodeColumn(dialect, columnMetaData.getName())
                         , "=", "#{data.", columnMetaData.getAlias(),

+ 28 - 32
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/main/java/org/hswebframework/web/dao/mybatis/builder/jpa/JpaAnnotationParser.java

@@ -15,10 +15,7 @@ import org.hswebframework.web.dict.EnumDict;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.util.StringUtils;
 
-import javax.persistence.Column;
-import javax.persistence.Enumerated;
-import javax.persistence.Lob;
-import javax.persistence.Table;
+import javax.persistence.*;
 import java.beans.PropertyDescriptor;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
@@ -109,25 +106,31 @@ public class JpaAnnotationParser {
     }
 
 
-    public static RDBTableMetaData parseMetaDataFromEntity(Class entityClass) {
-        Table table = AnnotationUtils.findAnnotation(entityClass, Table.class);
-        if (table == null) {
-            return null;
-        }
-        RDBTableMetaData tableMetaData = new RDBTableMetaData();
-        tableMetaData.setName(table.name());
+    private static List<RDBColumnMetaData> parseColumnMeta(String prefix, String columnName, Class entityClass) {
 
         PropertyDescriptor[] descriptors = BeanUtilsBean.getInstance()
                 .getPropertyUtils()
                 .getPropertyDescriptors(entityClass);
+        List<RDBColumnMetaData> columnMetaDataList = new ArrayList<>();
+
         for (PropertyDescriptor descriptor : descriptors) {
             Column columnAnn = getAnnotation(entityClass, descriptor, Column.class);
+            CollectionTable collectionTable = getAnnotation(entityClass, descriptor, CollectionTable.class);
+
             if (columnAnn == null) {
+                if (collectionTable != null) {
+                    columnMetaDataList.addAll(parseColumnMeta(descriptor.getName(), collectionTable.name(), descriptor.getPropertyType()));
+                    continue;
+                }
                 continue;
             }
+
+            String realName = StringUtils.hasText(columnAnn.name()) ? columnAnn.name() : descriptor.getName();
+            String realAlias = StringUtils.hasText(prefix) ? prefix.concat(".").concat(descriptor.getName()) : descriptor.getName();
+
             RDBColumnMetaData column = new RDBColumnMetaData();
-            column.setName(columnAnn.name());
-            column.setAlias(descriptor.getName());
+            column.setName(StringUtils.hasText(columnName) ? columnName.concat(".").concat(realName) : realName);
+            column.setAlias(realAlias);
             column.setLength(columnAnn.length());
             column.setPrecision(columnAnn.precision());
             column.setJavaType(descriptor.getPropertyType());
@@ -151,26 +154,19 @@ public class JpaAnnotationParser {
                         .orElse(JDBCType.OTHER);
             }
             column.setJdbcType(type);
-            ValueConverter dateConvert = new DateTimeConverter("yyyy-MM-dd HH:mm:ss", column.getJavaType()) {
-                @Override
-                public Object getData(Object value) {
-                    if (value instanceof Number) {
-                        return new Date(((Number) value).longValue());
-                    }
-                    return super.getData(value);
-                }
-            };
-
-            if (column.getJdbcType() == JDBCType.DATE
-                    || column.getJdbcType() == JDBCType.TIMESTAMP) {
-                column.setValueConverter(dateConvert);
-            } else if (column.getJavaType() == boolean.class || column.getJavaType() == Boolean.class) {
-                column.setValueConverter(new BooleanValueConverter(column.getJdbcType()));
-            } else if (TypeUtils.isNumberType(column)) {
-                column.setValueConverter(new NumberValueConverter(column.getJavaType()));
-            }
-            tableMetaData.addColumn(column);
+            columnMetaDataList.add(column);
         }
+        return columnMetaDataList;
+    }
+
+    public static RDBTableMetaData parseMetaDataFromEntity(Class entityClass) {
+        Table table = AnnotationUtils.findAnnotation(entityClass, Table.class);
+        if (table == null) {
+            return null;
+        }
+        RDBTableMetaData tableMetaData = new RDBTableMetaData();
+        tableMetaData.setName(table.name());
+        parseColumnMeta(null, null, entityClass).forEach(tableMetaData::addColumn);
         return tableMetaData;
     }
 

+ 49 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/main/java/org/hswebframework/web/dao/mybatis/handler/NumberBooleanTypeHandler.java

@@ -0,0 +1,49 @@
+package org.hswebframework.web.dao.mybatis.handler;
+
+import org.apache.ibatis.type.*;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@Alias("numberBooleanTypeHandler")
+@MappedTypes({Boolean.class})
+@MappedJdbcTypes({JdbcType.NUMERIC, JdbcType.BOOLEAN})
+public class NumberBooleanTypeHandler implements TypeHandler<Object> {
+    @Override
+    public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
+        if (parameter == null) {
+            ps.setNull(i, jdbcType.TYPE_CODE);
+            return;
+        }
+        if(parameter instanceof Number){
+            if (jdbcType == JdbcType.BOOLEAN) {
+                ps.setBoolean(i, ((Number) parameter).intValue()==1);
+            }else{
+                ps.setInt(i,((Number) parameter).intValue());
+            }
+        }else{
+            if (jdbcType == JdbcType.BOOLEAN) {
+                ps.setBoolean(i, Boolean.TRUE.equals(parameter));
+            } else {
+                ps.setInt(i, Boolean.TRUE.equals(parameter) ? 1 : 0);
+            }
+        }
+    }
+
+    @Override
+    public Object getResult(ResultSet rs, String columnName) throws SQLException {
+        return rs.getBoolean(columnName);
+    }
+
+    @Override
+    public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
+        return rs.getBoolean(columnIndex);
+    }
+
+    @Override
+    public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
+        return cs.getBoolean(columnIndex);
+    }
+}

+ 4 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/java/org/hswebframework/web/dao/crud/NestEntity.java

@@ -2,6 +2,8 @@ package org.hswebframework.web.dao.crud;
 
 import lombok.Data;
 
+import javax.persistence.Column;
+
 /**
  *
  * @author zhouhao
@@ -9,5 +11,7 @@ import lombok.Data;
  */
 @Data
 public class NestEntity {
+
+    @Column
     private String name;
 }

+ 5 - 3
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/java/org/hswebframework/web/dao/crud/TestCrud.java

@@ -77,14 +77,16 @@ public class TestCrud extends AbstractTransactionalJUnit4SpringContextTests {
         //#102
         query.where("createTime", "2017-11-10");
 
-//        query.includes("nest.name", "*");
 
 //        DataSourceHolder.tableSwitcher().use("h_test", "h_test2");
         List<TestEntity> entities = testDao.queryNest(query);
-
+        query.includes("name");
+        testDao.count(query);
         testDao.query(query);
+
+        query.includes("nest.name", "*");
         testDao.countNest(query);
-        testDao.count(query);
+
         UpdateParamEntity.newUpdate()
                 .set("name","测试")
                 .set(entity::getDataType)

+ 1 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/java/org/hswebframework/web/dao/crud/TestEntity.java

@@ -44,6 +44,7 @@ public class TestEntity implements org.hswebframework.web.commons.entity.Entity
     )
     private DataType[] dataTypes;
 
+    @CollectionTable(name = "nest_table")
     private NestEntity nest;
 
 }

+ 4 - 1
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/resources/org/hswebframework/web/dao/test/TestDao.xml

@@ -10,7 +10,10 @@
 
     <resultMap id="TestNestResultMap" type="org.hswebframework.web.dao.crud.TestEntity">
         <id property="id" column="id" javaType="Long" jdbcType="INTEGER"/>
-        <result property="nest.name" column="nest_table.name" javaType="String" jdbcType="VARCHAR"/>
+<!--        <result property="nest.name" column="nest_table.name" javaType="String" jdbcType="VARCHAR"/>-->
+<!--        <association property="nest" column="nest_table">-->
+<!--            <result column="name" jdbcType="VARCHAR" javaType="String"/>-->
+<!--        </association>-->
     </resultMap>
 
     <!--用于动态生成sql所需的配置-->