diff --git a/src/main/java/org/redkale/asm/AsmMethodBean.java b/src/main/java/org/redkale/asm/AsmMethodBean.java index 018ad5dd9..67f3077bd 100644 --- a/src/main/java/org/redkale/asm/AsmMethodBean.java +++ b/src/main/java/org/redkale/asm/AsmMethodBean.java @@ -13,7 +13,7 @@ import org.redkale.convert.json.JsonConvert; * 存放方法的字节信息 * * @see org.redkale.asm.AsmMethodBoost - * + * * @since 2.8.0 */ public class AsmMethodBean { @@ -65,6 +65,17 @@ public class AsmMethodBean { } } + public List fieldNameList() { + if (params == null) { + return new ArrayList<>(); + } + List rs = new ArrayList<>(params.size()); + for (AsmMethodParam p : params) { + rs.add(p.getName()); + } + return rs; + } + public String[] fieldNameArray() { if (params == null) { return null; diff --git a/src/main/java/org/redkale/persistence/Sql.java b/src/main/java/org/redkale/persistence/Sql.java new file mode 100644 index 000000000..5a7d92a85 --- /dev/null +++ b/src/main/java/org/redkale/persistence/Sql.java @@ -0,0 +1,33 @@ +/* + * + */ +package org.redkale.persistence; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 原始sql语句 + * + * + *

+ * 详情见: https://redkale.org + * + * @see org.redkale.source.DataSqlMapper + * + * @author zhangjx + * + * @since 2.8.0 + */ +@Inherited +@Documented +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Sql { + + String value(); +} diff --git a/src/main/java/org/redkale/source/AbstractDataSqlSource.java b/src/main/java/org/redkale/source/AbstractDataSqlSource.java index f385e3765..3533f9812 100644 --- a/src/main/java/org/redkale/source/AbstractDataSqlSource.java +++ b/src/main/java/org/redkale/source/AbstractDataSqlSource.java @@ -18,6 +18,7 @@ import org.redkale.annotation.*; import org.redkale.annotation.AutoLoad; import org.redkale.annotation.ResourceType; import static org.redkale.boot.Application.*; +import org.redkale.convert.ConvertDisabled; import org.redkale.inject.ResourceEvent; import org.redkale.net.AsyncGroup; import org.redkale.persistence.Table; @@ -654,6 +655,11 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement return nativeSqlParser.parse(signFunc, dbtype(), nativeSql, params == null ? Collections.emptyMap() : params); } + @ConvertDisabled + public IntFunction getSignFunc() { + return signFunc; + } + @Override public void destroy(AnyValue config) { super.destroy(config); diff --git a/src/main/java/org/redkale/source/DataSqlMapper.java b/src/main/java/org/redkale/source/DataSqlMapper.java index 9f891b2cb..e5e116c98 100644 --- a/src/main/java/org/redkale/source/DataSqlMapper.java +++ b/src/main/java/org/redkale/source/DataSqlMapper.java @@ -22,6 +22,7 @@ import org.redkale.util.Sheet; *

* 详情见: https://redkale.org * + * @see org.redkale.persistence.Sql * * @author zhangjx * @param T @@ -3309,97 +3310,4 @@ public interface DataSqlMapper { return dataSource().querySheetAsync(entityType(), selects, flipper, node); } - //----------------------- native ---------------------------- - /** - * 执行多条原生无参数的sql - * - * @param sqls 无参数的sql语句 - * - * @return 执行条数 - */ - default int[] nativeUpdates(String... sqls) { - return dataSource().nativeUpdates(sqls); - } - - /** - * 执行多条原生无参数的sql - * - * @param sqls 无参数的sql语句 - * - * @return 执行条数 - */ - default CompletableFuture nativeUpdatesAsync(String... sqls) { - return dataSource().nativeUpdatesAsync(sqls); - } - - /** - * 执行原生无参数的sql - * - * @param sql 无参数的sql语句 - * - * @return 执行条数 - */ - default int nativeUpdate(String sql) { - return dataSource().nativeUpdate(sql); - } - - /** - * 执行原生无参数的sql - * - * @param sql 无参数的sql语句 - * - * @return 执行条数 - */ - default CompletableFuture nativeUpdateAsync(String sql) { - return dataSource().nativeUpdateAsync(sql); - } - - /** - * 执行原生带参数的sql - * - * @param sql 带参数的sql语句 - * @param params 参数值集合 - * - * @return 执行条数 - */ - default int nativeUpdate(String sql, Map params) { - return dataSource().nativeUpdate(sql, params); - } - - /** - * 执行原生带参数的sql - * - * @param sql 带参数的sql语句 - * @param params 参数值集合 - * - * @return 执行条数 - */ - default CompletableFuture nativeUpdateAsync(String sql, Map params) { - return dataSource().nativeUpdateAsync(sql, params); - } - - /** - * 执行原生带参数的sql - * - * @param sql 带参数的sql语句 - * @param bean 参数值集合 - * - * @return 执行条数 - */ - default int nativeUpdate(String sql, Serializable bean) { - return dataSource().nativeUpdate(sql, bean); - } - - /** - * 执行原生带参数的sql - * - * @param sql 带参数的sql语句 - * @param bean 参数值集合 - * - * @return 执行条数 - */ - default CompletableFuture nativeUpdateAsync(String sql, Serializable bean) { - return dataSource().nativeUpdateAsync(sql, bean); - } - } diff --git a/src/main/java/org/redkale/source/DataSqlSource.java b/src/main/java/org/redkale/source/DataSqlSource.java index 577b6db42..441fea9b8 100644 --- a/src/main/java/org/redkale/source/DataSqlSource.java +++ b/src/main/java/org/redkale/source/DataSqlSource.java @@ -7,6 +7,7 @@ import java.io.Serializable; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.*; +import org.redkale.asm.AsmDepends; import static org.redkale.source.DataResultSet.formatColumnValue; import org.redkale.util.*; @@ -20,6 +21,7 @@ import org.redkale.util.*; * @author zhangjx * @since 2.8.0 */ +@AsmDepends public interface DataSqlSource extends DataSource { /** diff --git a/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java b/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java index c860b721b..317fe519b 100644 --- a/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java +++ b/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java @@ -3,9 +3,48 @@ */ package org.redkale.source.spi; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.IntFunction; +import org.redkale.asm.AnnotationVisitor; +import org.redkale.asm.AsmMethodBean; +import org.redkale.asm.AsmMethodBoost; +import org.redkale.asm.ClassWriter; +import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES; +import org.redkale.asm.FieldVisitor; +import org.redkale.asm.Label; +import org.redkale.asm.MethodVisitor; +import static org.redkale.asm.Opcodes.ACC_PRIVATE; +import static org.redkale.asm.Opcodes.ACC_PUBLIC; +import static org.redkale.asm.Opcodes.ACC_SUPER; +import static org.redkale.asm.Opcodes.ALOAD; +import static org.redkale.asm.Opcodes.ARETURN; +import static org.redkale.asm.Opcodes.ASTORE; +import static org.redkale.asm.Opcodes.DUP; +import static org.redkale.asm.Opcodes.GETFIELD; +import static org.redkale.asm.Opcodes.INVOKEINTERFACE; +import static org.redkale.asm.Opcodes.INVOKESPECIAL; +import static org.redkale.asm.Opcodes.INVOKEVIRTUAL; +import static org.redkale.asm.Opcodes.NEW; +import static org.redkale.asm.Opcodes.POP; +import static org.redkale.asm.Opcodes.RETURN; +import static org.redkale.asm.Opcodes.V11; +import org.redkale.asm.Type; +import org.redkale.persistence.Sql; +import org.redkale.source.AbstractDataSqlSource; +import org.redkale.source.DataNativeSqlInfo; import org.redkale.source.DataNativeSqlParser; import org.redkale.source.DataSqlMapper; import org.redkale.source.DataSqlSource; +import org.redkale.source.SourceException; +import org.redkale.util.RedkaleClassLoader; +import org.redkale.util.TypeToken; +import org.redkale.util.Utility; /** * DataSqlMapper工厂类 @@ -20,10 +59,215 @@ import org.redkale.source.DataSqlSource; */ public final class DataSqlMapperBuilder { + private static Map baseMethodBeans; + private DataSqlMapperBuilder() { } public static > M createMapper(DataNativeSqlParser nativeSqlParser, DataSqlSource source, Class mapperType) { - return null; + if (!mapperType.isInterface()) { + throw new SourceException(mapperType + " is not interface"); + } + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + final Class entityType = entityType(mapperType); + final String supDynName = mapperType.getName().replace('.', '/'); + final String newDynName = "org/redkaledyn/source/mapper/_DynDataSqlMapper__" + supDynName.replace('$', '_'); + try { + Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.')); + Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz; + M mapper = (M) newClazz.getDeclaredConstructor().newInstance(); + { + Field c = newClazz.getDeclaredField("_source"); + c.setAccessible(true); + c.set(mapper, source); + } + { + Field c = newClazz.getDeclaredField("_type"); + c.setAccessible(true); + c.set(mapper, entityType); + } + return mapper; + } catch (ClassNotFoundException e) { + //do nothing + } catch (Throwable t) { + t.printStackTrace(); + } + + if (baseMethodBeans == null) { + baseMethodBeans = AsmMethodBoost.getMethodBeans(DataSqlMapper.class); + } + List items = new ArrayList<>(); + Map selfMethodBeans = AsmMethodBoost.getMethodBeans(mapperType); + for (Method method : mapperType.getMethods()) { + if (Modifier.isStatic(method.getModifiers())) { + continue; + } + if ("dataSource".equals(method.getName()) && method.getParameterCount() == 0) { + continue; + } + if ("entityType".equals(method.getName()) && method.getParameterCount() == 0) { + continue; + } + Sql sql = method.getAnnotation(Sql.class); + if (sql == null) { + if (Modifier.isAbstract(method.getModifiers())) { + throw new SourceException(method + " require @" + Sql.class.getSimpleName()); + } + continue; + } + if (!Modifier.isAbstract(method.getModifiers())) { + throw new SourceException(method + " is not abstract, but contains @" + Sql.class.getSimpleName()); + } + IntFunction signFunc = null; + if (source instanceof AbstractDataSqlSource) { + signFunc = ((AbstractDataSqlSource) source).getSignFunc(); + } + DataNativeSqlInfo sqlInfo = nativeSqlParser.parse(signFunc, source.getType(), sql.value()); + AsmMethodBean methodBean = selfMethodBeans.get(AsmMethodBoost.getMethodBeanKey(method)); + if (!Utility.equalsElement(sqlInfo.getRootParamNames(), methodBean.fieldNameList())) { + throw new SourceException(method + " parameters not match @" + Sql.class.getSimpleName() + "(" + sql.value() + ")"); + } + items.add(new Item(method, sqlInfo, methodBean)); + } + //------------------------------------------------------------------------------ + + final String entityDesc = Type.getDescriptor(entityType); + final String sqlSourceDesc = Type.getDescriptor(DataSqlSource.class); + + ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(V11, ACC_PUBLIC + ACC_SUPER, newDynName, null, "java/lang/Object", new String[]{supDynName}); + { + fv = cw.visitField(ACC_PRIVATE, "_source", sqlSourceDesc, null, null); + fv.visitEnd(); + } + { + fv = cw.visitField(ACC_PRIVATE, "_type", "Ljava/lang/Class;", null, null); + fv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "dataSource", "()Lorg/redkale/source/DataSqlSource;", null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, "org/redkale/test/source/parser/DynForumInfoMapperImpl", "source", sqlSourceDesc); + mv.visitInsn(ARETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "entityType", "()Ljava/lang/Class;", "()Ljava/lang/Class<" + entityDesc + ">;", null); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, newDynName, "type", "Ljava/lang/Class;"); + mv.visitInsn(ARETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + //sql系列方法 + for (Item item : items) { + Method method = item.method; + DataNativeSqlInfo sqlInfo = item.sqlInfo; + AsmMethodBean methodBean = item.methodBean; + Sql sql = method.getAnnotation(Sql.class); + + mv = cw.visitMethod(ACC_PUBLIC, "queryForumResultAsync", "(Lorg/redkale/test/source/parser/ForumBean;)Ljava/util/concurrent/CompletableFuture;", "(Lorg/redkale/test/source/parser/ForumBean;)Ljava/util/concurrent/CompletableFuture;>;", null); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLdcInsn(sql.value()); + mv.visitVarInsn(ASTORE, 2); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitTypeInsn(NEW, "java/util/HashMap"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "", "()V", false); + mv.visitVarInsn(ASTORE, 3); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitVarInsn(ALOAD, 3); + mv.visitLdcInsn("bean"); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true); + mv.visitInsn(POP); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/test/source/parser/DynForumInfoMapperImpl", "dataSource", "()Lorg/redkale/source/DataSqlSource;", false); + mv.visitLdcInsn(Type.getType("Lorg/redkale/test/source/parser/ForumResult;")); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 3); + mv.visitMethodInsn(INVOKEINTERFACE, "org/redkale/source/DataSqlSource", "nativeQueryListAsync", "(Ljava/lang/Class;Ljava/lang/String;Ljava/util/Map;)Ljava/util/concurrent/CompletableFuture;", true); + mv.visitInsn(ARETURN); + Label l4 = new Label(); + mv.visitLabel(l4); + mv.visitLocalVariable("this", "Lorg/redkale/test/source/parser/DynForumInfoMapperImpl;", null, l0, l4, 0); + mv.visitLocalVariable("bean", "Lorg/redkale/test/source/parser/ForumBean;", null, l0, l4, 1); + mv.visitLocalVariable("sql", "Ljava/lang/String;", null, l1, l4, 2); + mv.visitLocalVariable("params", "Ljava/util/Map;", "Ljava/util/Map;", l2, l4, 3); + mv.visitMaxs(4, 4); + mv.visitEnd(); + } + + cw.visitEnd(); + + byte[] bytes = cw.toByteArray(); + Class newClazz = new ClassLoader(loader) { + public final Class loadClass(String name, byte[] b) { + return defineClass(name, b, 0, b.length); + } + }.loadClass(newDynName.replace('/', '.'), bytes); + RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz); + RedkaleClassLoader.putReflectionPublicConstructors(newClazz, newDynName.replace('/', '.')); + RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.')); + try { + M mapper = (M) newClazz.getDeclaredConstructor().newInstance(); + { + Field c = newClazz.getDeclaredField("_source"); + c.setAccessible(true); + c.set(mapper, source); + } + { + Field c = newClazz.getDeclaredField("_type"); + c.setAccessible(true); + c.set(mapper, entityType); + } + return mapper; + } catch (Exception ex) { + throw new SourceException(ex); + } + } + + private static Class entityType(Class mapperType) { + for (java.lang.reflect.Type t : mapperType.getGenericInterfaces()) { + if (DataSqlMapper.class.isAssignableFrom(TypeToken.typeToClass(t))) { + return TypeToken.typeToClass(((ParameterizedType) t).getActualTypeArguments()[0]); + } + } + throw new SourceException("Not found entity class from " + mapperType.getName()); + } + + private static class Item { + + public Method method; + + public DataNativeSqlInfo sqlInfo; + + public AsmMethodBean methodBean; + + public Item(Method method, DataNativeSqlInfo sqlInfo, AsmMethodBean methodBean) { + this.method = method; + this.sqlInfo = sqlInfo; + this.methodBean = methodBean; + } + } } diff --git a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java index 6895a6894..1476c5d9f 100644 --- a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java +++ b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java @@ -516,9 +516,14 @@ public class SourceModuleEngine extends ModuleEngine implements SourceManager { if ((srcObj instanceof Service) && Sncp.isRemote((Service) srcObj)) { return null; //远程模式不得注入 } + DataSqlMapper old = resourceFactory.find(resourceName, DataSqlMapper.class); + if (old != null) { + return old; + } DataSource source = loadDataSource(resourceName, false); Class mapperType = field.getType(); DataSqlMapper mapper = DataSqlMapperBuilder.createMapper(nativeSqlParser, (DataSqlSource) source, mapperType); + resourceFactory.register(resourceName, DataSqlMapper.class, mapper); field.set(srcObj, mapper); return mapper; } catch (Exception e) { diff --git a/src/test/java/org/redkale/test/source/parser/BaseEntity.java b/src/test/java/org/redkale/test/source/parser/BaseEntity.java new file mode 100644 index 000000000..156591164 --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/BaseEntity.java @@ -0,0 +1,25 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.test.source.parser; + +import java.io.*; +import org.redkale.convert.json.*; +import org.redkale.persistence.*; + +/** + * + * @author zhangjx + */ +@Entity +public abstract class BaseEntity implements Serializable { + + + @Override + public String toString() { + return JsonConvert.root().convertTo(this); + } + +} diff --git a/src/test/java/org/redkale/test/source/parser/BaseMapper.java b/src/test/java/org/redkale/test/source/parser/BaseMapper.java new file mode 100644 index 000000000..4da7503fc --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/BaseMapper.java @@ -0,0 +1,14 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import org.redkale.source.DataSqlMapper; + +/** + * + * @author zhangjx + */ +public interface BaseMapper extends DataSqlMapper { + +} diff --git a/src/test/java/org/redkale/test/source/parser/DataSqlMapperTest.java b/src/test/java/org/redkale/test/source/parser/DataSqlMapperTest.java new file mode 100644 index 000000000..4cf015324 --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/DataSqlMapperTest.java @@ -0,0 +1,39 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import org.junit.jupiter.api.Test; +import org.redkale.source.DataSqlMapper; +import org.redkale.source.SourceException; +import org.redkale.util.TypeToken; + +/** + * + * @author zhangjx + */ +public class DataSqlMapperTest { + + public static void main(String[] args) throws Throwable { + DataSqlMapperTest test = new DataSqlMapperTest(); + test.run(); + + System.out.println(entityType(ForumInfoMapper.class)); + } + + private static Class entityType(Class mapperType) { + for (Type t : mapperType.getGenericInterfaces()) { + if (DataSqlMapper.class.isAssignableFrom(TypeToken.typeToClass(t))) { + return TypeToken.typeToClass(((ParameterizedType) t).getActualTypeArguments()[0]); + } + } + throw new SourceException("Not found entity class from " + mapperType.getName()); + } + + @Test + public void run() throws Exception { + + } +} diff --git a/src/test/java/org/redkale/test/source/parser/DynForumInfoMapperImpl.java b/src/test/java/org/redkale/test/source/parser/DynForumInfoMapperImpl.java new file mode 100644 index 000000000..2e47e87df --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/DynForumInfoMapperImpl.java @@ -0,0 +1,62 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import org.redkale.source.DataSqlSource; + +/** + * + * @author zhangjx + */ +public class DynForumInfoMapperImpl implements ForumInfoMapper { + + private DataSqlSource source; + + private Class type; + + @Override + public ForumResult findForumResult(ForumBean bean) { + String sql = "SELECT f.forum_groupid, s.forum_section_color FROM forum_info f, forum_section s WHERE f.forumid = s.forumid"; + Map params = new HashMap<>(); + params.put("bean", bean); + return dataSource().nativeQueryOne(ForumResult.class, sql, params); + } + + public CompletableFuture findForumResultAsync(ForumBean bean) { + String sql = "SELECT f.forum_groupid, s.forum_section_color FROM forum_info f, forum_section s WHERE f.forumid = s.forumid"; + Map params = new HashMap<>(); + params.put("bean", bean); + return dataSource().nativeQueryOneAsync(ForumResult.class, sql, params); + } + + @Override + public List queryForumResult(ForumBean bean) { + String sql = "SELECT f.forum_groupid, s.forum_section_color FROM forum_info f, forum_section s WHERE f.forumid = s.forumid"; + Map params = new HashMap<>(); + params.put("bean", bean); + return dataSource().nativeQueryList(ForumResult.class, sql, params); + } + + public CompletableFuture> queryForumResultAsync(ForumBean bean) { + String sql = "SELECT f.forum_groupid, s.forum_section_color FROM forum_info f, forum_section s WHERE f.forumid = s.forumid"; + Map params = new HashMap<>(); + params.put("bean", bean); + return dataSource().nativeQueryListAsync(ForumResult.class, sql, params); + } + + @Override + public DataSqlSource dataSource() { + return source; + } + + @Override + public Class entityType() { + return type; + } + +} diff --git a/src/test/java/org/redkale/test/source/parser/ForumBean.java b/src/test/java/org/redkale/test/source/parser/ForumBean.java new file mode 100644 index 000000000..e8a0d57b6 --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/ForumBean.java @@ -0,0 +1,44 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import java.io.Serializable; + +/** + * + * @author zhangjx + */ +public class ForumBean implements Serializable { + + private String forumSectionid; + + private String forumSectionColor; + + private String forumid; + + public String getForumSectionid() { + return forumSectionid; + } + + public void setForumSectionid(String forumSectionid) { + this.forumSectionid = forumSectionid; + } + + public String getForumSectionColor() { + return forumSectionColor; + } + + public void setForumSectionColor(String forumSectionColor) { + this.forumSectionColor = forumSectionColor; + } + + public String getForumid() { + return forumid; + } + + public void setForumid(String forumid) { + this.forumid = forumid; + } + +} diff --git a/src/test/java/org/redkale/test/source/parser/ForumInfo.java b/src/test/java/org/redkale/test/source/parser/ForumInfo.java new file mode 100644 index 000000000..406db698c --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/ForumInfo.java @@ -0,0 +1,259 @@ +package org.redkale.test.source.parser; + +import java.util.*; +import org.redkale.convert.*; +import org.redkale.persistence.*; +import org.redkale.util.Utility; + +/** + * + * @author zhangjx + */ +@Table(name = "forum_info", comment = "论坛信息表") +public class ForumInfo extends BaseEntity implements Comparable { + + @Id + @Column(name = "forum_id", length = 64, comment = "论坛ID") + private String forumid; + + @Column(name = "forum_name", length = 128, comment = "论坛的名称") + private String forumName; + + @Column(name = "forum_groupid", length = 64, comment = "论坛分类的ID") + private String forumGroupid; + + @Column(name = "forum_sections", length = 1024, comment = "论坛小版块的ID集合") + private String[] forumSections; + + @Column(name = "forum_managerids", length = 1024, comment = "论坛小版块的ID集合") + private Set forumManagerids; + + @Column(name = "forum_face_url", length = 255, comment = "论坛的图片url") + private String forumFaceUrl; + + @Column(name = "forum_css_img_url", length = 255, comment = "论坛的背景图url") + private String forumCssImgUrl; + + @Column(name = "forum_css_url", length = 255, comment = "论坛的样式url") + private String forumCssUrl; + + @Column(name = "forum_css_content", length = 10240, comment = "论坛的css内容") + private String forumCssContent; + + @Column(name = "forum_bar_html", length = 1024, comment = "版块的提示栏") + private String forumBarHtml; + + @Column(name = "forum_desc", length = 255, comment = "论坛说明") + private String forumDesc; + + @Column(name = "forum_notice", length = 1024, comment = "论坛公告") + private String forumNotice; + + @Column(comment = "被关注的用户数") + private long followers; + + @Column(name = "post_count", comment = "帖子数") + private long postCount; + + @Column(name = "like_count", comment = "关注数") + private long likeCount; + + @Column(comment = "排序顺序,值小靠前") + private int display = 1000; + + @Transient + private Map sections; + + public ForumSection findForumSection(String forumSectionid) { + return sections == null ? null : sections.get(forumSectionid); + } + + public synchronized void increLikeCount() { + this.likeCount++; + } + + public synchronized void increPostCount(String sectionid) { + this.postCount++; + if (sections != null && sectionid != null && !sectionid.isEmpty()) { + ForumSection section = sections.get(sectionid); + if (section != null) { + section.increPostCount(); + } + } + } + + public synchronized void increFollowers() { + this.followers++; + } + + public synchronized void decreFollowers() { + this.followers--; + } + + public boolean containsManagerid(int userid) { + return forumManagerids != null && forumManagerids.contains(userid); + } + + public boolean containsSection(String forumSectionid) { + return forumSections != null && forumSectionid != null && Utility.contains(forumSections, forumSectionid); + } + + public boolean emptyForumNotice() { + return this.forumNotice == null || this.forumNotice.isEmpty(); + } + + public boolean emptyCssImgUrl() { + return this.forumCssImgUrl == null || this.forumCssImgUrl.isEmpty(); + } + + public boolean emptyCssUrl() { + return this.forumCssUrl == null || this.forumCssUrl.isEmpty(); + } + + public boolean emptyCssContent() { + return this.forumCssContent == null || this.forumCssContent.isEmpty(); + } + + public void setForumid(String forumid) { + this.forumid = forumid; + } + + public String getForumid() { + return this.forumid; + } + + public void setForumName(String forumName) { + this.forumName = forumName; + } + + public String getForumName() { + return this.forumName; + } + + public void setForumFaceUrl(String forumFaceUrl) { + this.forumFaceUrl = forumFaceUrl; + } + + public String getForumFaceUrl() { + return this.forumFaceUrl; + } + + public String getForumCssImgUrl() { + return forumCssImgUrl; + } + + public void setForumCssImgUrl(String forumCssImgUrl) { + this.forumCssImgUrl = forumCssImgUrl; + } + + public String getForumCssUrl() { + return forumCssUrl; + } + + public void setForumCssUrl(String forumCssUrl) { + this.forumCssUrl = forumCssUrl; + } + + public String getForumCssContent() { + return forumCssContent; + } + + public void setForumCssContent(String forumCssContent) { + this.forumCssContent = forumCssContent; + } + + public String[] getForumSections() { + return forumSections; + } + + public void setForumSections(String[] forumSections) { + this.forumSections = forumSections; + } + + public Set getForumManagerids() { + return forumManagerids; + } + + public void setForumManagerids(Set forumManagerids) { + this.forumManagerids = forumManagerids; + } + + public String getForumGroupid() { + return forumGroupid; + } + + public void setForumGroupid(String forumGroupid) { + this.forumGroupid = forumGroupid; + } + + public String getForumDesc() { + return forumDesc; + } + + public void setForumDesc(String forumDesc) { + this.forumDesc = forumDesc; + } + + public String getForumNotice() { + return forumNotice; + } + + public void setForumNotice(String forumNotice) { + this.forumNotice = forumNotice; + } + + public long getFollowers() { + return followers; + } + + public void setFollowers(long followers) { + this.followers = followers; + } + + public void setPostCount(long postCount) { + this.postCount = postCount; + } + + public long getPostCount() { + return this.postCount; + } + + public long getLikeCount() { + return likeCount; + } + + public void setLikeCount(long likeCount) { + this.likeCount = likeCount; + } + + public void setDisplay(int display) { + this.display = display; + } + + @ConvertColumn(ignore = true, type = ConvertType.PROTOBUF_JSON) + public int getDisplay() { + return this.display; + } + + @Override + public int compareTo(ForumInfo o) { + return this.display - o.display; + } + + public Map getSections() { + return sections; + } + + public void setSections(Map sections) { + this.sections = sections; + } + + public String getForumBarHtml() { + return forumBarHtml; + } + + public void setForumBarHtml(String forumBarHtml) { + this.forumBarHtml = forumBarHtml; + } + +} diff --git a/src/test/java/org/redkale/test/source/parser/ForumInfoMapper.java b/src/test/java/org/redkale/test/source/parser/ForumInfoMapper.java new file mode 100644 index 000000000..c1ea3e268 --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/ForumInfoMapper.java @@ -0,0 +1,43 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import org.redkale.persistence.Sql; + +/** + * + * @author zhangjx + */ +public interface ForumInfoMapper extends BaseMapper { + + @Sql("SELECT f.forum_groupid, s.forum_section_color " + + "FROM forum_info f, forum_section s " + + " WHERE f.forumid = s.forumid AND " + + "s.forum_sectionid = ${bean.forumSectionid} AND " + + "f.forumid = ${bean.forumid} AND s.forum_section_color = ${bean.forumSectionColor}") + public ForumResult findForumResult(ForumBean bean); + + @Sql("SELECT f.forum_groupid, s.forum_section_color " + + "FROM forum_info f, forum_section s " + + " WHERE f.forumid = s.forumid AND " + + "s.forum_sectionid = ${bean.forumSectionid} AND " + + "f.forumid = ${bean.forumid} AND s.forum_section_color = ${bean.forumSectionColor}") + public CompletableFuture findForumResultAsync(ForumBean bean); + + @Sql("SELECT f.forum_groupid, s.forum_section_color " + + "FROM forum_info f, forum_section s " + + " WHERE f.forumid = s.forumid AND " + + "s.forum_sectionid = ${bean.forumSectionid} AND " + + "f.forumid = ${bean.forumid} AND s.forum_section_color = ${bean.forumSectionColor}") + public List queryForumResult(ForumBean bean); + + @Sql("SELECT f.forum_groupid, s.forum_section_color " + + "FROM forum_info f, forum_section s " + + " WHERE f.forumid = s.forumid AND " + + "s.forum_sectionid = ${bean.forumSectionid} AND " + + "f.forumid = ${bean.forumid} AND s.forum_section_color = ${bean.forumSectionColor}") + public CompletableFuture> queryForumResultAsync(ForumBean bean); +} diff --git a/src/test/java/org/redkale/test/source/parser/ForumResult.java b/src/test/java/org/redkale/test/source/parser/ForumResult.java new file mode 100644 index 000000000..e7b76307c --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/ForumResult.java @@ -0,0 +1,39 @@ +/* + * + */ +package org.redkale.test.source.parser; + +import org.redkale.convert.json.JsonConvert; + +/** + * + * @author zhangjx + */ +public class ForumResult { + + private String forumGroupid; + + private String forumSectionColor; + + public String getForumGroupid() { + return forumGroupid; + } + + public void setForumGroupid(String forumGroupid) { + this.forumGroupid = forumGroupid; + } + + public String getForumSectionColor() { + return forumSectionColor; + } + + public void setForumSectionColor(String forumSectionColor) { + this.forumSectionColor = forumSectionColor; + } + + @Override + public String toString() { + return JsonConvert.root().convertTo(this); + } + +} diff --git a/src/test/java/org/redkale/test/source/parser/ForumSection.java b/src/test/java/org/redkale/test/source/parser/ForumSection.java new file mode 100644 index 000000000..8728f15f5 --- /dev/null +++ b/src/test/java/org/redkale/test/source/parser/ForumSection.java @@ -0,0 +1,134 @@ +package org.redkale.test.source.parser; + +import java.util.Set; +import org.redkale.convert.*; +import org.redkale.persistence.*; + +/** + * + * @author zhangjx + */ +@Table(name = "forum_section", comment = "论坛小版块信息表") +public class ForumSection extends BaseEntity { + + @Id + @Column(name = "forum_sectionid", length = 64, comment = "论坛小版块ID") + private String forumSectionid; + + @Column(length = 64, comment = "论坛ID") + private String forumid; + + @Column(name = "forum_section_name", length = 128, comment = "论坛小版块的名称") + private String forumSectionName; + + @Column(name = "forum_section_face_url", length = 255, comment = "论坛小版块的图标url") + private String forumSectionFaceUrl; + + @Column(name = "forum_section_managerids", length = 1024, comment = "论坛小版块的ID集合") + private Set forumSectionManagerids; + + @Column(name = "forum_section_desc", length = 32, comment = "论坛小版块说明") + private String forumSectionDesc; + + @Column(name = "forum_section_color", length = 255, comment = "论坛小版块小标题的背景色") + private String forumSectionColor; + + @Column(name = "forum_section_bar_html", length = 1024, comment = "版块的提示栏") + private String forumSectionBarHtml; + + @Column(name = "post_count", comment = "帖子数") + private long postCount; + + @Column(comment = "排序顺序,值小靠前") + private int display = 1000; + + public void increPostCount() { + this.postCount++; + } + + public boolean containsSectionManagerid(int userid) { + return forumSectionManagerids != null && forumSectionManagerids.contains(userid); + } + + public void setForumSectionid(String forumSectionid) { + this.forumSectionid = forumSectionid; + } + + public String getForumSectionid() { + return this.forumSectionid; + } + + public String getForumid() { + return forumid; + } + + public void setForumid(String forumid) { + this.forumid = forumid; + } + + public void setForumSectionName(String forumSectionName) { + this.forumSectionName = forumSectionName; + } + + public String getForumSectionName() { + return this.forumSectionName; + } + + public void setForumSectionFaceUrl(String forumSectionFaceUrl) { + this.forumSectionFaceUrl = forumSectionFaceUrl; + } + + public String getForumSectionFaceUrl() { + return this.forumSectionFaceUrl; + } + + public String getForumSectionColor() { + return forumSectionColor; + } + + public void setForumSectionColor(String forumSectionColor) { + this.forumSectionColor = forumSectionColor; + } + + public void setForumSectionDesc(String forumSectionDesc) { + this.forumSectionDesc = forumSectionDesc; + } + + public Set getForumSectionManagerids() { + return forumSectionManagerids; + } + + public void setForumSectionManagerids(Set forumSectionManagerids) { + this.forumSectionManagerids = forumSectionManagerids; + } + + public String getForumSectionDesc() { + return this.forumSectionDesc; + } + + public void setPostCount(long postCount) { + this.postCount = postCount; + } + + public long getPostCount() { + return this.postCount; + } + + public void setDisplay(int display) { + this.display = display; + } + + @ConvertColumn(ignore = true, type = ConvertType.PROTOBUF_JSON) + public int getDisplay() { + return this.display; + } + + public String getForumSectionBarHtml() { + return forumSectionBarHtml; + } + + public void setForumSectionBarHtml(String forumSectionBarHtml) { + this.forumSectionBarHtml = forumSectionBarHtml; + } + +}