Commit f80bd7c1 authored by 薛涛 Toby Xue's avatar 薛涛 Toby Xue 🆒

#1971 actionListener

parent c3f628bb
package logwire.web.bo;
import logwire.web.service.query.QueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BoService {
@Autowired
QueryService queryService;
}
package logwire.web.bo.bean;
import logwire.core.bo.handler.OperationHandler;
import logwire.core.bo.object.BizObject;
public class TypeOperationHandlerBean {
public TypeOperationHandlerBean(Class<? extends BizObject> bizObject, Class<? extends OperationHandler> handler) {
this.bizObject = bizObject;
this.handler = handler;
}
private Class<? extends BizObject> bizObject;
private Class<? extends OperationHandler> handler;
public Class getBizObject() {
return bizObject;
}
public void setBizObject(Class<? extends BizObject> bizObject) {
this.bizObject = bizObject;
}
public Class getHandler() {
return handler;
}
public void setHandler(Class<? extends OperationHandler> handler) {
this.handler = handler;
}
}
package logwire.web.bo.container;
public abstract class BoBeanContainer<T> {
public abstract T getBean(String id);
}
package logwire.web.bo.container;
import logwire.core.resource.*;
import logwire.web.bo.loader.BoRelationBeanDefinitionLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class BoRelationBeanContainerBuilder implements JavaBeanContainerBuilder {
@Override
public JavaBeanContainer build(ApplicationContext applicationContext) {
return newContainer(applicationContext, BoRelationBeanDefinitionLoader.class);
}
@Override
public String getContainerName() {
return "BO_RELATION";
}
private JavaBeanContainer newContainer(ApplicationContext ctx, Class... classes) {
BeanLoader[] loaders = new BeanLoader[classes.length];
for (int i = 0; i < loaders.length; i++) {
loaders[i] = (BeanLoader) Util.getExactBean(ctx, classes[i]);
}
JavaBeanContainer container = new JavaBeanContainer(loaders);
return container;
}
}
package logwire.web.bo.container;
import logwire.web.bo.bean.TypeOperationHandlerBean;
import java.util.ArrayList;
import java.util.List;
public class OperationHandlerContainer {
private List<TypeOperationHandlerBean> typeOperationHandlerBeanList = new ArrayList<>();
public List<TypeOperationHandlerBean> getTypeOperationHandlerBeanList() {
return typeOperationHandlerBeanList;
}
public void setTypeOperationHandlerBeanList(List<TypeOperationHandlerBean> typeOperationHandlerBeanList) {
this.typeOperationHandlerBeanList = typeOperationHandlerBeanList;
}
public void addTypeOperationHandlerBean(TypeOperationHandlerBean typeOperationHandlerBean) {
this.typeOperationHandlerBeanList.add(typeOperationHandlerBean);
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.BigIntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BigIntegerFieldParser extends FieldParser<BigIntegerField> {
@Override
protected BigIntegerField newField(Field field, Annotation[] annotations) {
return new BigIntegerField(field.getName());
}
@Override
protected void setField(BigIntegerField newField, Annotation[] annotations) {
}
private BigIntegerFieldParser() {
}
public static BigIntegerFieldParser getInstance() {
return BigIntegerFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static BigIntegerFieldParser instance = new BigIntegerFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.StringField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BizArrayFieldParser extends FieldParser<StringField> {
@Override
protected StringField newField(Field field, Annotation[] annotations) {
return new StringField(field.getName(), 100);
}
private BizArrayFieldParser() {
}
public static BizArrayFieldParser getInstance() {
return BizArrayFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static BizArrayFieldParser instance = new BizArrayFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.BooleanField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BooleanFieldParser extends FieldParser<BooleanField> {
@Override
protected BooleanField newField(Field field, Annotation[] annotations) {
return new BooleanField(field.getName());
}
private BooleanFieldParser() {
}
public static BooleanFieldParser getInstance() {
return BooleanFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static BooleanFieldParser instance = new BooleanFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.DateTimeField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DateTimeFieldParser extends FieldParser<DateTimeField> {
@Override
protected DateTimeField newField(Field field, Annotation[] annotations) {
return new DateTimeField(field.getName());
}
private DateTimeFieldParser() {
}
public static DateTimeFieldParser getInstance() {
return DateTimeFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static DateTimeFieldParser instance = new DateTimeFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.DecimalField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DecimalFieldParser extends FieldParser<DecimalField> {
@Override
protected DecimalField newField(Field field, Annotation[] annotations) {
return new DecimalField(field.getName(), 18, 6);
}
private DecimalFieldParser() {
}
public static DecimalFieldParser getInstance() {
return DecimalFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static DecimalFieldParser instance = new DecimalFieldParser();
}
}
package logwire.web.bo.field.parse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public abstract class FieldParser<T extends logwire.core.meta.model.fields.Field> {
protected abstract T newField(Field field, Annotation[] annotations);
public T parse(Field field, Annotation[] annotations) {
T newField = newField(field, annotations);
setField(newField, annotations);
return newField;
}
protected void setField(T newField, Annotation[] annotations) {
}
}
package logwire.web.bo.field.parse;
import logwire.core.bo.field.BizArray;
import java.lang.annotation.Annotation;
import java.time.OffsetDateTime;
public abstract class FieldParserUtil {
private FieldParserUtil() {
}
/**
* 获取解析注解的 parser
*
* @param field
* @param annotations
* @return
*/
public static FieldParser getParser(java.lang.reflect.Field field, Annotation[] annotations) {
return getParserByFieldType(field);
}
private static FieldParser getParserByFieldType(java.lang.reflect.Field field) {
// 此时一定是存在 Field 类型的 annotation
// 根据字段类型来推断 Parser
Class clazz = field.getType();
if (clazz.equals(String.class)) {
return StringFieldParser.getInstance();
} else if (clazz.equals(Integer.class) || clazz.equals(int.class)) {
return IntegerFieldParser.getInstance();
} else if (clazz.equals(Short.class) || clazz.equals(short.class)) {
return SmallIntegerFieldParser.getInstance();
} else if (clazz.equals(Long.class) || clazz.equals(long.class)) {
return BigIntegerFieldParser.getInstance();
} else if (clazz.equals(OffsetDateTime.class) || clazz.equals(java.util.Date.class)) {
return DateTimeFieldParser.getInstance();
} else if (clazz.equals(Boolean.class) || clazz.equals(boolean.class)) {
return BooleanFieldParser.getInstance();
} else if (clazz.equals(Double.class) || clazz.equals(double.class) || clazz.equals(float.class)) {
return DecimalFieldParser.getInstance();
} else if (clazz.equals(BizArray.class)) {
return BizArrayFieldParser.getInstance();
}
return null;
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.IntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class IntegerFieldParser extends FieldParser<IntegerField> {
@Override
protected IntegerField newField(Field field, Annotation[] annotations) {
return new IntegerField(field.getName());
}
private IntegerFieldParser() {
}
public static IntegerFieldParser getInstance() {
return IntegerFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static IntegerFieldParser instance = new IntegerFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.SmallIntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class SmallIntegerFieldParser extends FieldParser<SmallIntegerField> {
@Override
protected SmallIntegerField newField(Field field, Annotation[] annotations) {
return new SmallIntegerField(field.getName());
}
private SmallIntegerFieldParser() {
}
public static SmallIntegerFieldParser getInstance() {
return SmallIntegerFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static SmallIntegerFieldParser instance = new SmallIntegerFieldParser();
}
}
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.StringField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class StringFieldParser extends FieldParser<StringField> {
@Override
protected StringField newField(Field field, Annotation[] annotations) {
return new StringField(field.getName(), 50);
}
private StringFieldParser() {
}
public static StringFieldParser getInstance() {
return StringFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static StringFieldParser instance = new StringFieldParser();
}
}
package logwire.web.bo.handler;
import logwire.core.bo.handler.TypeOperationHandler;
public class CreateOperationHandler implements TypeOperationHandler {
@Override
public Object execute(Class aClass, Object... args) {
return null;
}
@Override
public String getOperation() {
return "create";
}
@Override
public boolean isEnabled() {
return true;
}
}
package logwire.web.bo.listener;
import logwire.core.meta.query.IQuery;
import logwire.core.meta.query.Query;
import logwire.web.action.listener.ActionListener;
import logwire.web.bo.query.BizModelQuery;
import logwire.web.bo.session.Session;
import logwire.web.bo.session.SessionHolder;
import logwire.web.service.ActionContext;
import logwire.web.service.query.QueryService;
import logwire.web.tenant.TenantProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BoActionListener implements ActionListener {
@Autowired
TenantProjectService projectService;
@Autowired
QueryService queryService;
@Override
public void beforeAction(ActionContext actionContext, String queryName) {
IQuery iQuery = projectService.getCurrentProject().findQuery(queryName);
if (iQuery == null) {
return;
}
if (!(iQuery instanceof Query)) {
return;
}
Query query = (Query) iQuery;
if (query instanceof BizModelQuery) {
SessionHolder.openSession(actionContext);
}
}
@Override
public void afterAction(ActionContext actionContext, String queryName) {
Session session = SessionHolder.getSession();
if (session != null) {
session.commit(queryService);
}
}
}
...@@ -10,11 +10,14 @@ import logwire.core.resource.BeanLoader; ...@@ -10,11 +10,14 @@ import logwire.core.resource.BeanLoader;
import logwire.core.resource.loader.JavaModelBeanLoader; import logwire.core.resource.loader.JavaModelBeanLoader;
import logwire.core.tenant.TenantClassLoader; import logwire.core.tenant.TenantClassLoader;
import logwire.core.tenant.TenantProject; import logwire.core.tenant.TenantProject;
import logwire.web.bo.field.parse.FieldParser;
import logwire.web.bo.field.parse.FieldParserUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
...@@ -26,6 +29,17 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme ...@@ -26,6 +29,17 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
@Autowired @Autowired
LoaderUtil loaderUtil; LoaderUtil loaderUtil;
/**
* load BoModel 的逻辑:
* 1、先遍历出所有BizObject的子类
* 2、将直接继承BizObject的类初始化
* 3、剩余的类中,判断是否独立的model(包含BizModel注解),若是,生成Model;若不是,字段添加至父类的Model中
*
* @param project 当前租户
* @param input 待加载的资源
* @param consumer 处理加载结果
* @throws Exception
*/
@Override @Override
public void load(TenantProject project, TenantProject input, Consumer<IQuery> consumer) throws Exception { public void load(TenantProject project, TenantProject input, Consumer<IQuery> consumer) throws Exception {
TenantClassLoader classLoader = project.getTenantBeanContext().getTenantClassLoader(); TenantClassLoader classLoader = project.getTenantBeanContext().getTenantClassLoader();
...@@ -44,33 +58,22 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme ...@@ -44,33 +58,22 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
} }
}).collect(Collectors.toList()); }).collect(Collectors.toList());
for (BeanDefinition beanDefinition : bizModelList) {
for (BeanDefinition beanDefinition : beans) {
Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName()); Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
//判断是否独立model //独立model
BizModel bizModelAnnotation = clazz.getAnnotation(BizModel.class); Model model = new Model();
if (bizModelAnnotation != null) { model.setName(clazz.getSimpleName());
//独立model model.setVerboseName(clazz.getAnnotation(BizModel.class).label());
Model model = new Model(); model.setIncludeAuditFields(true);
model.setName(clazz.getSimpleName()); model.setIncludeVersionField(true);
model.setName(clazz.getSimpleName()); model.setIncludeDomainField(true);
model.setVerboseName(bizModelAnnotation.label()); initField(clazz, model);
model.setIncludeAuditFields(true); /*
model.setIncludeVersionField(true); //todo
model.setIncludeDomainField(true); this.initIndex(clazz, model);
initField(clazz, model); this.initSign(model);*/
} else { consumer.accept(model);
//判断父类是否包含 @BizModel ,若包含则
}
/* this.initModel(clazz, model);
this.initFields(clazz, model);
this.initIndex(clazz, model);
this.initSign(model);
consumer.accept(model);*/
} }
...@@ -78,11 +81,18 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme ...@@ -78,11 +81,18 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
} }
private void initField(Class<?> clazz, Model model) { private void initField(Class<?> clazz, Model model) {
//获取所有带有Column注解的字段
Field[] fields = clazz.getDeclaredFields(); Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) { for (Field f : fields) {
Column column = f.getAnnotation(Column.class); Column column = f.getAnnotation(Column.class);
if (column != null) { if (column != null) {
/* model.*/ Annotation[] annotations = f.getDeclaredAnnotations();
FieldParser parser = FieldParserUtil.getParser(f, annotations);
if (parser == null) {
continue;
}
logwire.core.meta.model.fields.Field field = parser.parse(f, annotations);
model.addField(field);
} }
} }
} }
......
package logwire.web.bo.query;
public interface BizModelQuery {
}
package logwire.web.bo.session;
public class BizObjectStatus {
}
package logwire.web.bo.session;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import logwire.core.bo.object.BizObject;
import logwire.core.exceptions.ApplicationException;
import logwire.core.meta.model.Model;
import logwire.core.support.ApplicationContextHelper;
import logwire.web.security.SecurityUtil;
import logwire.web.security.TenantUser;
import logwire.web.service.ActionContext;
import logwire.web.service.event.BuiltinEventNames;
import logwire.web.service.query.QueryService;
import logwire.web.service.query.sql.QueryTransactionCode;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 业务对象操作上下文会话
*/
public class Session {
private ActionContext actionContext;
public Session(ActionContext actionContext) {
this.actionContext = actionContext;
}
/**
* 业务对象的缓存
* 第一层 map 的 key 为 model 名称
* 第二层 map 的 key 为 主键值
*/
private Map<String, Map<String, BizObject>> cache = Maps.newHashMap();
/**
* 业务对象主键值的缓存
* 第一层 map 的 key 为 model 名称
* 第二层 map 的 key 为 model 某个字段的名称
* 第三层 map 的 key 为 model 某个字段的值, value 为 model 主键的值
*/
private Map<String, Map<String, Map<String, Set<Object>>>> pkCache = Maps.newHashMap();
/**
* 保存业务对象之间的关系
* 第一层 map 的 key 为 明细表的 model 名称
* 第二层 map 的 key 为 明细表的主键值
* 第三层 map 的 value 为明细表对应的主表对应的业务对象
* <p>
* 保存时需要,先保存主表,再保存明细表
*/
private Map<String, Map<String, Set<BizObject>>> itemHeaderRelations = Maps.newHashMap();
/**
* 保存业务对象之间的关系
* 第一层 map 的 key 为 item 关系的主表对应的 model 名称
* 第二层 map 的 key 为 主键值
* 第三层 map 的 value 为 item 关系的明细表对应的业务对象
* <p>
* 删除时
* item 关系时,先删除明细表,再删除主表
*/
private Map<String, Map<String, Set<BizObject>>> headerItemRelations = Maps.newHashMap();
/**
* 保存业务对象之间的关系
* 第一层 map 的 key 为 join 关系的被 join 表
* 第二层 map 的 key 为 主键值
* 第三层 map 的 value 为 join 关系的主表
* <p>
* 删除时
* join 关系时,先删除主表,再删除被关联 JOIN 的表
*/
private Map<String, Map<String, Set<BizObject>>> joinOrExtendRelations = Maps.newHashMap();
/**
* 组合对象和业务对象的映射关系
* key 为 compositeObject.hashCode()
*/
private Map<Integer, BizObject> compositeBizObjectMapping = Maps.newHashMap();
/**
* 组合对象和业务对象中的组合对象类中属性名称的映射关系
* key 为 compositeObject.hashCode()
*/
private Map<Integer, String> compositeBizObjectFieldMapping = Maps.newHashMap();
/**
* 业务对象数据的存放
*/
private Map<Integer, OperableAgent> operableAgentMap = Maps.newHashMap();
/**
* 待持久化的业务对象
*/
private List<BizObject> bizObjects = Lists.newArrayList();
public ActionContext getActionContext() {
return actionContext;
}
/**
* 将业务对象存入上下文中
*
* @param t 业务对象
*/
public void add(BizObject t) {
if (t == null) {
return;
}
int existIndex = -1;
for (int i = 0; i < bizObjects.size(); i++) {
if (t.equals(bizObjects.get(i))) {
existIndex = i;
break;
}
}
bizObjects.add(t);
if (existIndex != -1) {
bizObjects.remove(existIndex);
}
}
private class PersistedRecorder {
/**
* 暂存已执行持久化操作的业务对象标记
*/
private Map<Integer, Boolean> record = Maps.newHashMap();
public void accept(BizObject t) {
record.put(t.hashCode(), true);
}
public boolean persistent(BizObject t) {
return record.containsKey(t.hashCode());
}
}
/**
* 持久化
*/
public void commit(QueryService queryService) {
if (this.bizObjects.isEmpty()) {
return;
}
PersistedRecorder persistedRecorder = new PersistedRecorder();
//待新增的业务对象
Map<String, List<BizObject>> insertBizObjects = Maps.newConcurrentMap();
//非待新增的业务对象
List<BizObject> otherBizObjects = Lists.newArrayList();
while (!this.bizObjects.isEmpty()) {
//将业务对象按照持久化方式分类为新增和其他
for (int i = 0; i < this.bizObjects.size(); i++) {
BizObject t = this.bizObjects.get(i);
if (QueryTransactionCode.TX_INSERT.equals(t.getTxCode())) {
List<BizObject> list = insertBizObjects.get(t.getModelName());
if (list == null) {
list = Lists.newArrayList();
insertBizObjects.put(t.getModelName(), list);
}
list.add(t);
} else {
otherBizObjects.add(t);
}
}
this.bizObjects.clear();
//执行新增操作
for (Map.Entry<String, List<BizObject>> entry : insertBizObjects.entrySet()) {
List<BizObject> bizObjects = entry.getValue();
if (bizObjects == null) {
continue;
}
for (int i = 0; i < bizObjects.size(); i++) {
BizObject bizObject = bizObjects.get(i);
if (persistedRecorder.persistent(bizObject)) {
continue;
}
persistedInsert(bizObject, queryService, persistedRecorder);
}
}
insertBizObjects.clear();
//执行编辑和删除操作
for (int i = 0; i < otherBizObjects.size(); i++) {
BizObject bizObject = otherBizObjects.get(i);
if (persistedRecorder.persistent(bizObject)) {
continue;
}
persisted(bizObject, queryService, persistedRecorder);
}
otherBizObjects.clear();
}
logwire.web.biz.session.SessionHolder.clear();
}
private void persistedHeader(BizObject t, QueryService queryService, PersistedRecorder persistedRecorder) {
//明细表有增删改时,头表一定要修改(如果不是新增的头表)而不管主表的数据是否有变化
Map<String, Set<BizObject>> headers = itemHeaderRelations.get(t.getModelName());
if (headers != null && !headers.isEmpty()) {
Set<BizObject> set = headers.get(t.getPkValue());
if (set == null || set.isEmpty()) {
return;
}
for (BizObject header : set) {
if (persistedRecorder.persistent(header)) {
continue;
}
BizObjectAgent agent = getOperableAgent(t);
agent.setForceUpdate();
persisted(header, queryService, persistedRecorder);
}
}
}
private void persistedInsert(BizObject t, QueryService queryService, PersistedRecorder persistedRecorder) {
BizObjectAgent agent = getOperableAgent(t);
TenantUser currentUser = SecurityUtil.currentUser();
if (BizObjectStatus.NEW_SAVE.equals(t.getBizObjectStatus())) {
agent.setInternal(QueryTransactionCode.TX_FIELD_NAME, QueryTransactionCode.TX_INSERT);
// persistedBefore(t, itemHeaderRelations, queryService); TODO 新增明细表前先新增主表
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_INSERT_BEFORE.name(), currentUser.getDomain(), t);
queryService.insert(t.getModelName(), t.toMap());
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_INSERT_AFTER.name(), currentUser.getDomain(), t);
persistedRecorder.accept(t);
persistedHeader(t, queryService, persistedRecorder);
}
}
private void persisted(BizObject t, QueryService queryService, PersistedRecorder persistedRecorder) {
BizObjectAgent agent = getOperableAgent(t);
TenantUser currentUser = SecurityUtil.currentUser();
if (BizObjectStatus.UPDATE.equals(t.getBizObjectStatus())) {
agent.setInternal(QueryTransactionCode.TX_FIELD_NAME, QueryTransactionCode.TX_UPDATE);
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_UPDATE_BEFORE.name(), currentUser.getDomain(), t);
queryService.update(t.getModelName(), t.toMap());
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_UPDATE_AFTER.name(), currentUser.getDomain(), t);
persistedRecorder.accept(t);
persistedHeader(t, queryService, persistedRecorder);
} else if (BizObjectStatus.DELETED.equals(t.getBizObjectStatus())) {
agent.setInternal(QueryTransactionCode.TX_FIELD_NAME, QueryTransactionCode.TX_DELETE);
persistedBefore(t, headerItemRelations, queryService, persistedRecorder);
persistedBefore(t, joinOrExtendRelations, queryService, persistedRecorder);
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_DELETE_BEFORE.name(), currentUser.getDomain(), t);
Model model = actionContext.model(t.getModelName());
boolean hasVersion = model.getIncludeVersionField();
boolean deleted;
Object pkValue = t.getPkValue();
if (hasVersion) {
deleted = queryService.delete(t.getModelName(), t.getPkValue(), (int) t.get(Model.VERSION_FIELD_NAME));
} else {
deleted = queryService.delete(t.getModelName(), t.getPkValue());
}
if (!deleted) {
throw new ApplicationException(model.getTenantProject().getMessageSourceAccessor().getMessage(
"failed.delete.biz-object", new Object[]{model.getVerboseNameI18n(), model.getPrimaryKeyField().getName(), pkValue},
String.format("删除失败:找不到或无权访问 [%s] 为 [%s] 的业务对象[%s]", model.getPrimaryKeyField().getName(), pkValue, model.getVerboseNameI18n())));
}
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_DELETE_AFTER.name(), currentUser.getDomain(), t);
persistedRecorder.accept(t);
persistedHeader(t, queryService, persistedRecorder);
}
}
private void persistedBefore(BizObject t, Map<String, Map<String, Set<BizObject>>> relations,
QueryService queryService, PersistedRecorder persistedRecorder) {
Map<String, Set<BizObject>> map = relations.get(t.getModelName());
if (map == null) {
return;
}
Set<? extends BizObject> set = map.get(t.getPkValue());
if (set == null || set.isEmpty()) {
return;
}
for (BizObject t2 : set) {
persistedInsert(t2, queryService, persistedRecorder);
persisted(t2, queryService, persistedRecorder);
}
}
public void flush() {
cache.clear();
pkCache.clear();
itemHeaderRelations.clear();
headerItemRelations.clear();
joinOrExtendRelations.clear();
compositeBizObjectMapping.clear();
compositeBizObjectFieldMapping.clear();
bizObjects.clear();
operableAgentMap.clear();
}
public BizObject getBizObjectByCompositeObject(Object compositeObject) {
if (compositeObject == null) {
return null;
}
return compositeBizObjectMapping.get(compositeObject.hashCode());
}
public String getBizObjectCompositeFieldNameByCompositeObject(Object compositeObject) {
if (compositeObject == null) {
return null;
}
return compositeBizObjectFieldMapping.get(compositeObject.hashCode());
}
public void cacheCompositeBizObject(BizObject bizObject, Object compositeObject, String compositeName) {
compositeBizObjectMapping.put(compositeObject.hashCode(), bizObject);
compositeBizObjectFieldMapping.put(compositeObject.hashCode(), compositeName);
}
public void cacheHeaderItemRelation(BizObject header, BizObject item) {
cacheBizObjectRelations(headerItemRelations, header, item);
cacheBizObjectRelations(itemHeaderRelations, item, header);
}
public void cacheJoinOrExtendRelation(BizObject main, BizObject joinOrExtend) {
cacheBizObjectRelations(joinOrExtendRelations, joinOrExtend, main);
}
private void cacheBizObjectRelations(Map<String, Map<String, Set<BizObject>>> relationsCollection, BizObject key, BizObject value) {
Object pkValue = key.getPkValue();
if (pkValue == null) {
return;
}
Map<String, Set<BizObject>> modelMap = relationsCollection.get(key.getModelName());
if (modelMap == null) {
modelMap = Maps.newHashMap();
relationsCollection.put(key.getModelName(), modelMap);
}
Set<BizObject> set = modelMap.get(pkValue.toString());
if (set == null) {
set = Sets.newHashSet();
modelMap.put(pkValue.toString(), set);
}
set.add(value);
}
/**
* 缓存根据某个字段作为查询条件加载得到的若干业务对象
* 此处只缓存业务对象中的主键值
* 因为 Session 是线程安全的,所以此处内部不考虑并发问题
*
* @param t
* @param fieldName
*/
public void cache(BizObject t, String fieldName) {
Object pkValue = t.getPkValue();
if (pkValue == null) {
return;
}
//拿到存放某个 model 的主键缓存值的 map
Map<String, Map<String, Set<Object>>> modelMap = pkCache.get(t.getModelName());
if (modelMap == null) {
modelMap = Maps.newHashMap();
pkCache.put(t.getModelName(), modelMap);
}
//拿到存放通过某个 model 的 某个字段查询得到的主键后缓存值的 map
Map<String, Set<Object>> fieldMap = modelMap.get(fieldName);
if (fieldMap == null) {
fieldMap = Maps.newHashMap();
modelMap.put(fieldName, fieldMap);
}
//拿到存放通过某个 model 的 某个字段查询得到的主键后缓存的主键值的列表
Object fieldValue = t.get(fieldName);
Set<Object> set = fieldMap.get(fieldValue.toString());
if (set == null) {
set = Sets.newHashSet();
fieldMap.put(fieldValue.toString(), set);
}
set.add(t.getPkValue());
fieldMap.put(fieldValue.toString(), set);
}
public void cacheAgent(OperableAgent agent) {
operableAgentMap.put(agent.getTarget().hashCode(), agent);
}
/**
* 缓存业务对象
* 因为 Session 是线程安全的,所以此处内部不考虑并发问题
*
* @param t
*/
public void cache(BizObject t) {
if (t == null) {
return;
}
Object pkValue = t.getPkValue();
if (pkValue == null) {
return;
}
Map<String, BizObject> map = cache.get(t.getModelName());
if (map == null) {
map = Maps.newHashMap();
cache.put(t.getModelName(), map);
}
map.put(pkValue.toString(), t);
}
public void remove(BizObject t) {
//删除缓存中的数据
Map<String, BizObject> map = cache.get(t.getModelName());
if (map == null) {
return;
}
Object pkValue = t.getPkValue();
if (pkValue == null) {
return;
}
if (map.containsKey(pkValue.toString())) {
map.remove(pkValue.toString());
}
bizObjects.remove(t);
}
private boolean isNew(BizObject t) {
return BizObjectStatus.NEW.equals(t.getBizObjectStatus());
}
/**
* 从上下文中获取之前加载过的业务对象
*
* @param modelName
* @param pkValue
* @return
*/
public <T extends BizObject> T get(String modelName, Object pkValue) {
if (modelName == null || pkValue == null) {
return null;
}
Map<String, BizObject> map = cache.get(modelName);
if (map == null) {
return null;
}
return (T) map.get(pkValue.toString());
}
/**
* 从上下文中获取之前加载过的业务对象
*
* @param modelName
* @param fieldName
* @param fieldValue
* @return
*/
public <T extends BizObject> List<T> get(String modelName, String fieldName, Object fieldValue) {
if (modelName == null || fieldName == null || fieldValue == null) {
return null;
}
Map<String, Map<String, Set<Object>>> modelMap = pkCache.get(modelName);
if (modelMap == null || modelMap.isEmpty()) {
return null;
}
Map<String, Set<Object>> fieldMap = modelMap.get(fieldName);
if (fieldMap == null || fieldMap.isEmpty()) {
return null;
}
Set pkValues = fieldMap.get(fieldValue.toString());
if (pkValues == null || pkValues.isEmpty()) {
return null;
}
List<T> result = Lists.newArrayList();
pkValues.forEach(pkValue -> {
T t = get(modelName, pkValue);
if (t != null) {
result.add(t);
}
});
return result;
}
public <T extends Operable, R extends OperableAgent> R getOperableAgent(T operable) {
return (R) operableAgentMap.get(operable.hashCode());
}
}
package logwire.web.bo.session;
import logwire.core.exceptions.ApplicationException;
import logwire.web.service.ActionContext;
import org.springframework.core.NamedThreadLocal;
/**
* SessionHolder
*
*/
public abstract class SessionHolder {
private static ThreadLocal<Session> sessionThreadLocal = new NamedThreadLocal<>("Biz context");
public static Session getSessionOrFail() {
Session session = sessionThreadLocal.get();
if (session != null) {
return session;
}
throw new ApplicationException("No session exists, please call method SessionHolder.openSession() to open a new session!");
}
public static Session getSession() {
return sessionThreadLocal.get();
}
public static Session openSession(ActionContext context) {
Session session = sessionThreadLocal.get();
if (session == null) {
session = new Session(context);
sessionThreadLocal.set(session);
}
return session;
}
public static void clear() {
sessionThreadLocal.remove();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment