diff --git a/src/main/java/org/redkale/asm/MethodDebugVisitor.java b/src/main/java/org/redkale/asm/MethodDebugVisitor.java index fa3a66716..cf01a34cf 100644 --- a/src/main/java/org/redkale/asm/MethodDebugVisitor.java +++ b/src/main/java/org/redkale/asm/MethodDebugVisitor.java @@ -193,7 +193,7 @@ public class MethodDebugVisitor extends MethodVisitor { public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { visitor.visitLocalVariable(name, desc, signature, start, end, index); if (debug) { - System.out.println("mv.visitLocalVariable(\"" + name + "\", \"" + desc + "\", \"" + signature + "\", null, null, -1);"); + System.out.println("mv.visitLocalVariable(\"" + name + "\", \"" + desc + "\", \"" + signature + "\", null, null, " + index + ");"); } } diff --git a/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java b/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java index 567bf338f..7de43885b 100644 --- a/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java +++ b/src/main/java/org/redkale/source/spi/DataSqlMapperBuilder.java @@ -23,26 +23,7 @@ import org.redkale.asm.FieldVisitor; import org.redkale.asm.Label; import org.redkale.asm.MethodDebugVisitor; import org.redkale.asm.MethodVisitor; -import static org.redkale.asm.Opcodes.AASTORE; -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.ANEWARRAY; -import static org.redkale.asm.Opcodes.ARETURN; -import static org.redkale.asm.Opcodes.CHECKCAST; -import static org.redkale.asm.Opcodes.DLOAD; -import static org.redkale.asm.Opcodes.DUP; -import static org.redkale.asm.Opcodes.FLOAD; -import static org.redkale.asm.Opcodes.GETFIELD; -import static org.redkale.asm.Opcodes.ILOAD; -import static org.redkale.asm.Opcodes.INVOKEINTERFACE; -import static org.redkale.asm.Opcodes.INVOKESPECIAL; -import static org.redkale.asm.Opcodes.INVOKESTATIC; -import static org.redkale.asm.Opcodes.INVOKEVIRTUAL; -import static org.redkale.asm.Opcodes.LLOAD; -import static org.redkale.asm.Opcodes.RETURN; -import static org.redkale.asm.Opcodes.V11; +import static org.redkale.asm.Opcodes.*; import org.redkale.asm.Type; import org.redkale.convert.json.JsonObject; import org.redkale.persistence.Sql; @@ -72,8 +53,6 @@ import org.redkale.util.Utility; */ public final class DataSqlMapperBuilder { - private static Map baseMethodBeans; - private DataSqlMapperBuilder() { } @@ -84,7 +63,7 @@ public final class DataSqlMapperBuilder { 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('$', '_'); + final String newDynName = "org/redkaledyn/source/mapper/_DynDataSqlMapper_" + mapperType.getName().replace('.', '_').replace('$', '_'); try { Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.')); Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz; @@ -106,9 +85,6 @@ public final class DataSqlMapperBuilder { t.printStackTrace(); } - if (baseMethodBeans == null) { - baseMethodBeans = AsmMethodBoost.getMethodBeans(DataSqlMapper.class); - } List items = new ArrayList<>(); Map selfMethodBeans = AsmMethodBoost.getMethodBeans(mapperType); for (Method method : mapperType.getMethods()) { @@ -124,12 +100,14 @@ public final class DataSqlMapperBuilder { Sql sql = method.getAnnotation(Sql.class); if (sql == null) { if (Modifier.isAbstract(method.getModifiers())) { - throw new SourceException(method + " require @" + Sql.class.getSimpleName()); + throw new SourceException(mapperType.getSimpleName() + + "." + method.getName() + " require @" + Sql.class.getSimpleName()); } continue; } if (!Modifier.isAbstract(method.getModifiers())) { - throw new SourceException(method + " is not abstract, but contains @" + Sql.class.getSimpleName()); + throw new SourceException(mapperType.getSimpleName() + "." + method.getName() + + " is not abstract, but contains @" + Sql.class.getSimpleName()); } if (method.getExceptionTypes().length > 0) { throw new SourceException("@" + Sql.class.getSimpleName() + " cannot on throw-exception method, but " + method); @@ -140,18 +118,33 @@ public final class DataSqlMapperBuilder { } 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() + ")"); - } + List fieldNames = methodBean.fieldNameList(); Class resultClass = resultClass(method); + int flipperIndex = -1; + if (resultClass.isAssignableFrom(Sheet.class)) { + Class[] pts = method.getParameterTypes(); + for (int i = 0; i < pts.length; i++) { + if (pts[i] == Flipper.class) { + flipperIndex = i; + break; + } + } + if (flipperIndex < 0) { + throw new SourceException(mapperType.getSimpleName() + "." + method.getName() + + " need Flipper type parameter on @" + Sql.class.getSimpleName() + "(" + sql.value() + ")"); + } + fieldNames.remove(flipperIndex); + } + if (!Utility.equalsElement(sqlInfo.getRootParamNames(), fieldNames)) { + throw new SourceException(mapperType.getSimpleName() + "." + method.getName() + + " parameters not match, fieldNames = " + fieldNames + ", sqlParams = " + sqlInfo.getRootParamNames() + ", methodBean = " + methodBean); + } if (sqlInfo.getSqlMode() != SELECT) { //非SELECT语句只能返回int或void - if (resultClass != Integer.class && resultClass != int.class - && resultClass != Void.class && resultClass != void.class) { - throw new SourceException("@" + Sql.class.getSimpleName() - + "(" + sql.value() + ") must on return int or void method, but " + method); + if (resultClass != Integer.class && resultClass != int.class) { + throw new SourceException("Update SQL must on return int method, but " + method); } } - items.add(new Item(method, sqlInfo, methodBean)); + items.add(new Item(method, sqlInfo, methodBean, flipperIndex)); } //------------------------------------------------------------------------------ @@ -220,6 +213,7 @@ public final class DataSqlMapperBuilder { Method method = item.method; DataNativeSqlInfo sqlInfo = item.sqlInfo; AsmMethodBean methodBean = item.methodBean; + int flipperIndex = item.flipperIndex; Sql sql = method.getAnnotation(Sql.class); Class resultClass = resultClass(method); Class[] componentTypes = resultComponentType(method); @@ -233,44 +227,51 @@ public final class DataSqlMapperBuilder { mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "dataSource", "()" + sqlSourceDesc, false); - //参数:结果类 - mv.visitLdcInsn(Type.getType(Type.getDescriptor(componentTypes[0]))); - if (resultClass.isAssignableFrom(Map.class)) { - mv.visitLdcInsn(Type.getType(Type.getDescriptor(componentTypes[1]))); + if (sqlInfo.getSqlMode() == SELECT) { + //参数:结果类 + mv.visitLdcInsn(Type.getType(Type.getDescriptor(componentTypes[0]))); + if (resultClass.isAssignableFrom(Map.class)) { + mv.visitLdcInsn(Type.getType(Type.getDescriptor(componentTypes[1]))); + } } //参数:sql mv.visitLdcInsn(sql.value()); + if (flipperIndex >= 0) { + mv.visitVarInsn(ALOAD, flipperIndex + 1); + } //参数: params - Asms.visitInsn(mv, paramTypes.length * 2); + Asms.visitInsn(mv, paramTypes.length * 2 - (flipperIndex >= 0 ? 2 : 0)); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); int insn = 0; for (int i = 0; i < paramTypes.length; i++) { insn++; - Class pt = paramTypes[i]; - //参数名 - mv.visitInsn(DUP); - Asms.visitInsn(mv, i * 2); - mv.visitLdcInsn(methodParams.get(i).getName()); - mv.visitInsn(AASTORE); - //参数值 - mv.visitInsn(DUP); - Asms.visitInsn(mv, i * 2 + 1); - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, insn++); - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, insn++); - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, insn++); + if (i != flipperIndex) { + Class pt = paramTypes[i]; + //参数名 + mv.visitInsn(DUP); + Asms.visitInsn(mv, i * 2); + mv.visitLdcInsn(methodParams.get(i).getName()); + mv.visitInsn(AASTORE); + //参数值 + mv.visitInsn(DUP); + Asms.visitInsn(mv, i * 2 + 1); + if (pt.isPrimitive()) { + if (pt == long.class) { + mv.visitVarInsn(LLOAD, insn++); + } else if (pt == float.class) { + mv.visitVarInsn(FLOAD, insn++); + } else if (pt == double.class) { + mv.visitVarInsn(DLOAD, insn++); + } else { + mv.visitVarInsn(ILOAD, insn); + } } else { - mv.visitVarInsn(ILOAD, insn); + mv.visitVarInsn(ALOAD, insn); } - } else { - mv.visitVarInsn(ALOAD, insn); + Asms.visitPrimitiveValueOf(mv, pt); + mv.visitInsn(AASTORE); } insns.add(insn); - Asms.visitPrimitiveValueOf(mv, pt); - mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKESTATIC, utilClassName, "ofMap", "([Ljava/lang/Object;)Ljava/util/HashMap;", false); @@ -305,10 +306,23 @@ public final class DataSqlMapperBuilder { if (oneMode) { mv.visitTypeInsn(CHECKCAST, componentTypes[0].getName().replace('.', '/')); } + mv.visitInsn(ARETURN); } else { - //UPDATE + String updateMethodName = "nativeUpdate" + (async ? "Async" : ""); + String updateMethodDesc = "(Ljava/lang/String;Ljava/util/Map;)" + (async ? "Ljava/util/concurrent/CompletableFuture;" : "I"); + mv.visitMethodInsn(INVOKEINTERFACE, sqlSourceName, updateMethodName, updateMethodDesc, true); + if (resultClass == int.class) { + mv.visitInsn(IRETURN); + } else if (!async && resultClass == Integer.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + mv.visitInsn(ARETURN); + } else if (resultClass == void.class) { + mv.visitInsn(POP); + mv.visitInsn(RETURN); + } else { + mv.visitInsn(ARETURN); + } } - mv.visitInsn(ARETURN); Label l2 = new Label(); mv.visitLabel(l2); mv.visitLocalVariable("this", "L" + newDynName + ";", null, l0, l2, 0); @@ -408,10 +422,13 @@ public final class DataSqlMapperBuilder { public AsmMethodBean methodBean; - public Item(Method method, DataNativeSqlInfo sqlInfo, AsmMethodBean methodBean) { + public int flipperIndex = -1; + + public Item(Method method, DataNativeSqlInfo sqlInfo, AsmMethodBean methodBean, int flipperIndex) { this.method = method; this.sqlInfo = sqlInfo; this.methodBean = methodBean; + this.flipperIndex = flipperIndex; } } diff --git a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java index 1476c5d9f..c65a38a61 100644 --- a/src/main/java/org/redkale/source/spi/SourceModuleEngine.java +++ b/src/main/java/org/redkale/source/spi/SourceModuleEngine.java @@ -516,14 +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); + Class mapperType = (Class) field.getType(); + DataSqlMapper old = resourceFactory.find(resourceName, mapperType); 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); + resourceFactory.register(resourceName, mapperType, mapper); field.set(srcObj, mapper); return mapper; } catch (Exception e) {