有一种业务情况类似下图,质控能做的项目是仪器关联的项目。这时候维护质控物时候开通项目时候要求加载仪器项目里面的项目(没有开通的子业务数据的部分)。对右边已经开通的部分要求加载仪器项目里面的项目(有开通业务子数据的部分)。开通的业务子数据又会随时间推移有成千上万的数据。
按老的ORM写法就要把几千个开通子数据查询出来判断项目有没有开通。像下面代码,性能随时间会下降,写法也不直观:
/**
* 查询能够开通的项目,老写法
* @return
*/
public String QueryOpenTestCode() throws Exception
{
//查是否有开通项目
boolean HasOpen=Helper.ValidParam(JRTContext.GetRequest(Request, "HasOpen"), false);
int MaterialDR=Helper.ValidParam(JRTContext.GetRequest(Request, "MaterialDR"), 0);
//得到质控物的数据
BTQCMaterial matDto=EntityManager().DolerGet(BTQCMaterial.class,MaterialDR);
BTMIMachineParameter machDto=EntityManager().DolerGet(BTMIMachineParameter.class,matDto.MachineDR);
//查询仪器项目
List<BTMIMachineTestCode> machTsList=EntityManager().FindByColVal(BTMIMachineTestCode.class,"MachineParameterDR",matDto.MachineDR);
//质控浓度数据
List<BTQCMaterialLevel> levList=EntityManager().FindByColVal(BTQCMaterialLevel.class,"MaterialDR",MaterialDR);
//返回列表
List<BTMIMachineTestCodeDto> retList=new ArrayList<>();
if(machTsList!=null&&machTsList.size()>0)
{
for(int i=0;i<machTsList.size();i++)
{
//没激活的不要
if(machTsList.get(i).Active==false)
{
continue;
}
for(int j=1;j<=matDto.Levels;j++)
{
HashParam hs=new HashParam();
hs.Add("MaterialDR",matDto.RowID);
hs.Add("TestCodeDR",machTsList.get(i).TestCodeDR);
hs.Add("LevelNo",j);
//写法性能低,如果质控换批次有几千个子批次数据,都要查询组装数据
List<BTQCMaterialTestCode> matTS=EntityManager().FindAllSimple(BTQCMaterialTestCode.class,hs);
boolean hasOpen=false;
if(matTS==null||matTS.size()==0)
{
hasOpen=false;
}
else
{
hasOpen=true;
}
//根据开通决定输出
if(hasOpen==HasOpen)
{
BTMIMachineTestCodeDto one=new BTMIMachineTestCodeDto();
one.LevelNo=j;
one.LevelNoName="";
for(BTQCMaterialLevel lev:levList)
{
if(lev.LevelNo==j)
{
one.LevelNoName=lev.CName;
}
}
//项目数据
BTTestCode tsDto=EntityManager().DolerGet(BTTestCode.class,machTsList.get(i).TestCodeDR);
one.TestCodeCode=tsDto.Code;
one.TestCodeDR=tsDto.RowID;
one.TestCodeSynonym=tsDto.Synonym;
one.TestCodeName=tsDto.CName;
retList.add(one);
}
}
}
}
return Helper.Object2Json(retList);
}
为了解决这种问题,ORM提供新api,直接用top 1查主键判断查询是否存在数据,减少SQL输出和查询压力。
用新api改进的写法
/**
* 查询能够开通的项目或者已经开通的项目,新写法
* @return
*/
public String QueryOpenTestCode() throws Exception
{
//查是否有开通项目
boolean HasOpen=Helper.ValidParam(JRTContext.GetRequest(Request, "HasOpen"), false);
//质控物主键
int MaterialDR=Helper.ValidParam(JRTContext.GetRequest(Request, "MaterialDR"), 0);
//得到质控物的数据
BTQCMaterial matDto=EntityManager().DolerGet(BTQCMaterial.class,MaterialDR);
//仪器数据
BTMIMachineParameter machDto=EntityManager().DolerGet(BTMIMachineParameter.class,matDto.MachineDR);
//查询仪器项目
List<BTMIMachineTestCode> machTsList=EntityManager().FindByColVal(BTMIMachineTestCode.class,"MachineParameterDR",matDto.MachineDR);
//质控浓度数据
List<BTQCMaterialLevel> levList=EntityManager().FindByColVal(BTQCMaterialLevel.class,"MaterialDR",MaterialDR);
//返回列表
List<BTMIMachineTestCodeDto> retList=new ArrayList<>();
if(machTsList!=null&&machTsList.size()>0)
{
for(int i=0;i<machTsList.size();i++)
{
//没激活的不要
if(machTsList.get(i).Active==false)
{
continue;
}
for(int j=1;j<=matDto.Levels;j++)
{
HashParam hs=new HashParam();
hs.Add("MaterialDR",matDto.RowID);
hs.Add("TestCodeDR",machTsList.get(i).TestCodeDR);
hs.Add("LevelNo",j);
//按条件检查是否有数据,直接用SQL,top 1 主键查询,更高效,碰到一行就返回一个注解,SQL性能更高,返回数据量小
boolean hasOpen=EntityManager().CheckHasData(BTQCMaterialTestCode.class,hs,null,null);
//根据开通决定输出
if(hasOpen==HasOpen)
{
BTMIMachineTestCodeDto one=new BTMIMachineTestCodeDto();
one.LevelNo=j;
one.LevelNoName="";
for(BTQCMaterialLevel lev:levList)
{
if(lev.LevelNo==j)
{
one.LevelNoName=lev.CName;
}
}
//项目数据
BTTestCode tsDto=EntityManager().DolerGet(BTTestCode.class,machTsList.get(i).TestCodeDR);
one.TestCodeCode=tsDto.Code;
one.TestCodeDR=tsDto.RowID;
one.TestCodeSynonym=tsDto.Synonym;
one.TestCodeName=tsDto.CName;
retList.add(one);
}
}
}
}
return Helper.Object2Json(retList);
}
对判断子表数据行数而又不需要具体数据的情况用下面的方法
对应复制数据的提供拷贝相同名称属性值方法,方便快速拷贝
干净利落,不再拖泥带水。