Ver Fonte

数据中心查询优化1

o2sword há 5 anos atrás
pai
commit
d3749652c5

+ 7 - 1
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/statement/ActionExecute.java

@@ -73,7 +73,13 @@ class ActionExecute extends BaseAction {
 				scriptContext);
 		String text = ScriptFactory.asString(o);
 		Class<? extends JpaObject> cls = this.clazz(business, statement);
-		EntityManager em = business.entityManagerContainer().get(cls);
+		EntityManager em;
+		if(StringUtils.equalsIgnoreCase(statement.getEntityCategory(), Statement.ENTITYCATEGORY_DYNAMIC)
+				&& StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)){
+			em = business.entityManagerContainer().get(DynamicBaseEntity.class);
+		}else{
+			em = business.entityManagerContainer().get(cls);
+		}
 		Query query = em.createQuery(text);
 		for (Parameter<?> p : query.getParameters()) {
 			if (runtime.hasParameter(p.getName())) {

+ 223 - 0
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/statement/ActionExecuteV2.java

@@ -0,0 +1,223 @@
+package com.x.query.assemble.designer.jaxrs.statement;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.entity.dynamic.DynamicBaseEntity;
+import com.x.base.core.entity.dynamic.DynamicEntity;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.script.AbstractResources;
+import com.x.base.core.project.script.ScriptFactory;
+import com.x.base.core.project.webservices.WebservicesClient;
+import com.x.organization.core.express.Organization;
+import com.x.query.assemble.designer.Business;
+import com.x.query.assemble.designer.ThisApplication;
+import com.x.query.core.entity.schema.Statement;
+import com.x.query.core.entity.schema.Table;
+import com.x.query.core.express.statement.Runtime;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Parameter;
+import javax.persistence.Query;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.SimpleScriptContext;
+import java.util.Objects;
+
+class ActionExecuteV2 extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionExecuteV2.class);
+
+	ActionResult<Object> execute(EffectivePerson effectivePerson, String flag, String mode, Integer page, Integer size,
+			JsonElement jsonElement) throws Exception {
+
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Object> result = new ActionResult<>();
+			Business business = new Business(emc);
+			Statement statement = emc.flag(flag, Statement.class);
+			if (null == statement) {
+				throw new ExceptionEntityNotExist(flag, Statement.class);
+			}
+			if (!business.executable(effectivePerson, statement)) {
+				throw new ExceptionAccessDenied(effectivePerson, statement);
+			}
+
+			Runtime runtime = this.runtime(effectivePerson, jsonElement, business, page, size);
+
+			Object data = null;
+			Object count = null;
+			switch (mode){
+				case Statement.MODE_DATA:
+					switch (Objects.toString(statement.getFormat(), "")) {
+						case Statement.FORMAT_SCRIPT:
+							data = this.script(effectivePerson, business, statement, runtime, mode);
+							break;
+						default:
+							data = this.jpql(effectivePerson, business, statement, runtime, mode);
+							break;
+					}
+					result.setData(data);
+					break;
+				case Statement.MODE_COUNT:
+					switch (Objects.toString(statement.getFormat(), "")) {
+						case Statement.FORMAT_SCRIPT:
+							count = this.script(effectivePerson, business, statement, runtime, mode);
+							break;
+						default:
+							count = this.jpql(effectivePerson, business, statement, runtime, mode);
+							break;
+					}
+					result.setData(count);
+					result.setCount((Long)count);
+					break;
+				default:
+					switch (Objects.toString(statement.getFormat(), "")) {
+						case Statement.FORMAT_SCRIPT:
+							data = this.script(effectivePerson, business, statement, runtime, Statement.MODE_DATA);
+							count = this.script(effectivePerson, business, statement, runtime, Statement.MODE_COUNT);
+							break;
+						default:
+							data = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_DATA);
+							count = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_COUNT);
+							break;
+					}
+					result.setData(data);
+					result.setCount((Long)count);
+			}
+			return result;
+		}
+	}
+
+	private Object script(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode)
+			throws Exception {
+		Object data = null;
+		ScriptContext scriptContext = this.scriptContext(effectivePerson, business, runtime);
+		ScriptFactory.initialServiceScriptText().eval(scriptContext);
+		String scriptText = statement.getScriptText();
+		if(Statement.MODE_COUNT.equals(mode)) {
+			scriptText = statement.getCountScriptText();
+		}
+		Object o = ScriptFactory.scriptEngine.eval(ScriptFactory.functionalization(scriptText),
+				scriptContext);
+		String text = ScriptFactory.asString(o);
+		Class<? extends JpaObject> cls = this.clazz(business, statement);
+		EntityManager em;
+		if(StringUtils.equalsIgnoreCase(statement.getEntityCategory(), Statement.ENTITYCATEGORY_DYNAMIC)
+				&& StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)){
+			em = business.entityManagerContainer().get(DynamicBaseEntity.class);
+		}else{
+			em = business.entityManagerContainer().get(cls);
+		}
+		Query query = em.createQuery(text);
+		for (Parameter<?> p : query.getParameters()) {
+			if (runtime.hasParameter(p.getName())) {
+				query.setParameter(p.getName(), runtime.getParameter(p.getName()));
+			}
+		}
+		if (StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
+			if(Statement.MODE_COUNT.equals(mode)) {
+				data = query.getSingleResult();
+			}else{
+				query.setFirstResult((runtime.page - 1) * runtime.size);
+				query.setMaxResults(runtime.size);
+				data = query.getResultList();
+			}
+		} else {
+			business.entityManagerContainer().beginTransaction(cls);
+			data = query.executeUpdate();
+			business.entityManagerContainer().commit();
+		}
+		return data;
+	}
+
+	private Object jpql(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode)
+			throws Exception {
+		Object data = null;
+		Class<? extends JpaObject> cls = this.clazz(business, statement);
+		EntityManager em;
+		if(StringUtils.equalsIgnoreCase(statement.getEntityCategory(), Statement.ENTITYCATEGORY_DYNAMIC)
+				&& StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)){
+			em = business.entityManagerContainer().get(DynamicBaseEntity.class);
+		}else{
+			em = business.entityManagerContainer().get(cls);
+		}
+		String jpqlData = statement.getData();
+		if(Statement.MODE_COUNT.equals(mode)) {
+			jpqlData = statement.getCountData();
+		}
+		Query query = em.createQuery(jpqlData);
+		for (Parameter<?> p : query.getParameters()) {
+			if (runtime.hasParameter(p.getName())) {
+				query.setParameter(p.getName(), runtime.getParameter(p.getName()));
+			}
+		}
+		if (StringUtils.equalsIgnoreCase(statement.getType(), Statement.TYPE_SELECT)) {
+			if(Statement.MODE_COUNT.equals(mode)) {
+				data = query.getSingleResult();
+			}else{
+				query.setFirstResult((runtime.page - 1) * runtime.size);
+				query.setMaxResults(runtime.size);
+				data = query.getResultList();
+			}
+		} else {
+			business.entityManagerContainer().beginTransaction(cls);
+			data = Integer.valueOf(query.executeUpdate());
+			business.entityManagerContainer().commit();
+		}
+		return data;
+	}
+
+	private Class<? extends JpaObject> clazz(Business business, Statement statement) throws Exception {
+		Class<? extends JpaObject> cls = null;
+		if (StringUtils.equals(Statement.ENTITYCATEGORY_OFFICIAL, statement.getEntityCategory())
+				|| StringUtils.equals(Statement.ENTITYCATEGORY_CUSTOM, statement.getEntityCategory())) {
+			cls = (Class<? extends JpaObject>) Class.forName(statement.getEntityClassName());
+		} else {
+			Table table = business.entityManagerContainer().flag(statement.getTable(), Table.class);
+			if (null == table) {
+				throw new ExceptionEntityNotExist(statement.getTable(), Table.class);
+			}
+			DynamicEntity dynamicEntity = new DynamicEntity(table.getName());
+			cls = (Class<? extends JpaObject>) Class.forName(dynamicEntity.className());
+		}
+		return cls;
+	}
+
+	private ScriptContext scriptContext(EffectivePerson effectivePerson, Business business, Runtime runtime)
+			throws Exception {
+		ScriptContext scriptContext = new SimpleScriptContext();
+		Resources resources = new Resources();
+		resources.setEntityManagerContainer(business.entityManagerContainer());
+		resources.setContext(ThisApplication.context());
+		resources.setApplications(ThisApplication.context().applications());
+		resources.setWebservicesClient(new WebservicesClient());
+		resources.setOrganization(new Organization(ThisApplication.context()));
+		Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+		bindings.put(ScriptFactory.BINDING_NAME_RESOURCES, resources);
+		bindings.put(ScriptFactory.BINDING_NAME_EFFECTIVEPERSON, effectivePerson);
+		bindings.put(ScriptFactory.BINDING_NAME_PARAMETERS, gson.toJson(runtime.getParameters()));
+		return scriptContext;
+	}
+
+	public static class Resources extends AbstractResources {
+
+		private Organization organization;
+
+		public Organization getOrganization() {
+			return organization;
+		}
+
+		public void setOrganization(Organization organization) {
+			this.organization = organization;
+		}
+
+	}
+
+}

+ 21 - 0
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/statement/StatementAction.java

@@ -142,4 +142,25 @@ public class StatementAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
+
+	@JaxrsMethodDescribe(value = "执行语句V2,可以同时执行查询结果及查询总数.", action = ActionExecuteV2.class)
+	@POST
+	@Path("{flag}/execute/mode/{mode}page/{page}/size/{size}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void executeV2(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+						@JaxrsParameterDescribe("标识") @PathParam("flag") String flag,
+						@JaxrsParameterDescribe("执行模式:data|count|all") @PathParam("mode") String mode,
+						@JaxrsParameterDescribe("页码") @PathParam("page") Integer page,
+						@JaxrsParameterDescribe("每页数量") @PathParam("size") Integer size, JsonElement jsonElement) {
+		ActionResult<Object> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionExecuteV2().execute(effectivePerson, flag, mode, page, size, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, jsonElement);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
 }

+ 52 - 2
o2server/x_query_core_entity/src/main/java/com/x/query/core/entity/schema/Statement.java

@@ -49,6 +49,9 @@ public class Statement extends SliceJpaObject {
 	public static final String TYPE_UPDATE = "update";
 	public static final String TYPE_INSERT = "insert";
 
+	public static final String MODE_DATA = "data";
+	public static final String MODE_COUNT = "count";
+
 	public static final String FORMAT_JPQL = "jpql";
 	public static final String FORMAT_SCRIPT = "script";
 
@@ -153,7 +156,7 @@ public class Statement extends SliceJpaObject {
 	@FieldDescribe("jpql语句.")
 	@Lob
 	@Basic(fetch = FetchType.EAGER)
-	@Column(length = JpaObject.length_10M, name = ColumnNamePrefix + data_FIELDNAME)
+	@Column(length = JpaObject.length_4K, name = ColumnNamePrefix + data_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String data;
 
@@ -161,10 +164,34 @@ public class Statement extends SliceJpaObject {
 	@FieldDescribe("类型为script的执行脚本.")
 	@Lob
 	@Basic(fetch = FetchType.EAGER)
-	@Column(length = JpaObject.length_10M, name = ColumnNamePrefix + scriptText_FIELDNAME)
+	@Column(length = JpaObject.length_32K, name = ColumnNamePrefix + scriptText_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String scriptText;
 
+	public static final String countData_FIELDNAME = "countData";
+	@FieldDescribe("jpql语句,用于查询总数.")
+	@Lob
+	@Basic(fetch = FetchType.EAGER)
+	@Column(length = JpaObject.length_4K, name = ColumnNamePrefix + countData_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String countData;
+
+	public static final String countScriptText_FIELDNAME = "countScriptText";
+	@FieldDescribe("类型为script的执行脚本,用于查询总数.")
+	@Lob
+	@Basic(fetch = FetchType.EAGER)
+	@Column(length = JpaObject.length_32K, name = ColumnNamePrefix + countScriptText_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String countScriptText;
+
+	public static final String view_FIELDNAME = "view";
+	@FieldDescribe("展现视图.")
+	@Lob
+	@Basic(fetch = FetchType.EAGER)
+	@Column(length = JpaObject.length_32K, name = ColumnNamePrefix + view_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String view;
+
 	public static final String creatorPerson_FIELDNAME = "creatorPerson";
 	@FieldDescribe("创建者")
 	@CheckPersist(allowEmpty = false)
@@ -322,4 +349,27 @@ public class Statement extends SliceJpaObject {
 		this.query = query;
 	}
 
+	public String getCountData() {
+		return countData;
+	}
+
+	public void setCountData(String countData) {
+		this.countData = countData;
+	}
+
+	public String getCountScriptText() {
+		return countScriptText;
+	}
+
+	public void setCountScriptText(String countScriptText) {
+		this.countScriptText = countScriptText;
+	}
+
+	public String getView() {
+		return view;
+	}
+
+	public void setView(String view) {
+		this.view = view;
+	}
 }