sql
This commit is contained in:
@@ -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<String> fieldNameList() {
|
||||
if (params == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> rs = new ArrayList<>(params.size());
|
||||
for (AsmMethodParam p : params) {
|
||||
rs.add(p.getName());
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
public String[] fieldNameArray() {
|
||||
if (params == null) {
|
||||
return null;
|
||||
|
||||
33
src/main/java/org/redkale/persistence/Sql.java
Normal file
33
src/main/java/org/redkale/persistence/Sql.java
Normal file
@@ -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语句
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* 详情见: 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();
|
||||
}
|
||||
@@ -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<String> getSignFunc() {
|
||||
return signFunc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(AnyValue config) {
|
||||
super.destroy(config);
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.redkale.util.Sheet;
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @see org.redkale.persistence.Sql
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> T
|
||||
@@ -3309,97 +3310,4 @@ public interface DataSqlMapper<T> {
|
||||
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<int[]> 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<Integer> nativeUpdateAsync(String sql) {
|
||||
return dataSource().nativeUpdateAsync(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行原生带参数的sql
|
||||
*
|
||||
* @param sql 带参数的sql语句
|
||||
* @param params 参数值集合
|
||||
*
|
||||
* @return 执行条数
|
||||
*/
|
||||
default int nativeUpdate(String sql, Map<String, Object> params) {
|
||||
return dataSource().nativeUpdate(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行原生带参数的sql
|
||||
*
|
||||
* @param sql 带参数的sql语句
|
||||
* @param params 参数值集合
|
||||
*
|
||||
* @return 执行条数
|
||||
*/
|
||||
default CompletableFuture<Integer> nativeUpdateAsync(String sql, Map<String, Object> 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<Integer> nativeUpdateAsync(String sql, Serializable bean) {
|
||||
return dataSource().nativeUpdateAsync(sql, bean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<String, AsmMethodBean> baseMethodBeans;
|
||||
|
||||
private DataSqlMapperBuilder() {
|
||||
}
|
||||
|
||||
public static <T, M extends DataSqlMapper<T>> M createMapper(DataNativeSqlParser nativeSqlParser, DataSqlSource source, Class<M> 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<Item> items = new ArrayList<>();
|
||||
Map<String, AsmMethodBean> 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<String> 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, "<init>", "()V", null, null);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()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<Ljava/util/List<Lorg/redkale/test/source/parser/ForumResult;>;>;", 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", "<init>", "()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<Ljava/lang/String;Ljava/lang/Object;>;", 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
25
src/test/java/org/redkale/test/source/parser/BaseEntity.java
Normal file
25
src/test/java/org/redkale/test/source/parser/BaseEntity.java
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
14
src/test/java/org/redkale/test/source/parser/BaseMapper.java
Normal file
14
src/test/java/org/redkale/test/source/parser/BaseMapper.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.test.source.parser;
|
||||
|
||||
import org.redkale.source.DataSqlMapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public interface BaseMapper<V> extends DataSqlMapper<V> {
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> params = new HashMap<>();
|
||||
params.put("bean", bean);
|
||||
return dataSource().nativeQueryOne(ForumResult.class, sql, params);
|
||||
}
|
||||
|
||||
public CompletableFuture<ForumResult> 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<String, Object> params = new HashMap<>();
|
||||
params.put("bean", bean);
|
||||
return dataSource().nativeQueryOneAsync(ForumResult.class, sql, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ForumResult> 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<String, Object> params = new HashMap<>();
|
||||
params.put("bean", bean);
|
||||
return dataSource().nativeQueryList(ForumResult.class, sql, params);
|
||||
}
|
||||
|
||||
public CompletableFuture<List<ForumResult>> 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<String, Object> params = new HashMap<>();
|
||||
params.put("bean", bean);
|
||||
return dataSource().nativeQueryListAsync(ForumResult.class, sql, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSqlSource dataSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ForumInfo> entityType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
44
src/test/java/org/redkale/test/source/parser/ForumBean.java
Normal file
44
src/test/java/org/redkale/test/source/parser/ForumBean.java
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
259
src/test/java/org/redkale/test/source/parser/ForumInfo.java
Normal file
259
src/test/java/org/redkale/test/source/parser/ForumInfo.java
Normal file
@@ -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<ForumInfo> {
|
||||
|
||||
@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<Integer> 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<String, ForumSection> 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<Integer> getForumManagerids() {
|
||||
return forumManagerids;
|
||||
}
|
||||
|
||||
public void setForumManagerids(Set<Integer> 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<String, ForumSection> getSections() {
|
||||
return sections;
|
||||
}
|
||||
|
||||
public void setSections(Map<String, ForumSection> sections) {
|
||||
this.sections = sections;
|
||||
}
|
||||
|
||||
public String getForumBarHtml() {
|
||||
return forumBarHtml;
|
||||
}
|
||||
|
||||
public void setForumBarHtml(String forumBarHtml) {
|
||||
this.forumBarHtml = forumBarHtml;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<ForumInfo> {
|
||||
|
||||
@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<ForumResult> 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<ForumResult> 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<List<ForumResult>> queryForumResultAsync(ForumBean bean);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
134
src/test/java/org/redkale/test/source/parser/ForumSection.java
Normal file
134
src/test/java/org/redkale/test/source/parser/ForumSection.java
Normal file
@@ -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<Integer> 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<Integer> getForumSectionManagerids() {
|
||||
return forumSectionManagerids;
|
||||
}
|
||||
|
||||
public void setForumSectionManagerids(Set<Integer> 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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user