IDEMPIERE-4960 Performance improvement for the opening of info window (#876)

* IDEMPIERE-4960 Performance improvement for the opening of info window

* IDEMPIERE-4960 Performance improvement for the opening of info window

Query.scroll and Query.list basically offer the same db performance, the
previous change is unnecessary.
This commit is contained in:
hengsin 2021-09-14 22:16:07 +08:00 committed by GitHub
parent a95983730f
commit 309eb5366f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 182 additions and 141 deletions

View File

@ -23,6 +23,7 @@ import org.compiere.model.X_AD_InfoProcess;
import org.compiere.util.Env;
import org.compiere.util.Evaluatee;
import org.compiere.util.Evaluator;
import org.idempiere.cache.ImmutablePOSupport;
/**
* Contain info of process in info window
@ -30,11 +31,12 @@ import org.compiere.util.Evaluator;
* @author hieplq
*
*/
public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn {
public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn, ImmutablePOSupport {
/**
*
*/
private static final long serialVersionUID = -5586972894900686397L;
private static final long serialVersionUID = 7833442401205258074L;
/**
* {@inheritDoc}
@ -115,5 +117,15 @@ public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn {
public MInfoColumn getAD_InfoColumn (){
return (MInfoColumn)super.getAD_InfoColumn();
}
@Override
public MInfoProcess markImmutable() {
if (is_Immutable())
return this;
makeImmutable();
return this;
}
}

View File

@ -21,12 +21,13 @@ import org.compiere.model.MInfoColumn;
import org.compiere.model.Query;
import org.compiere.model.X_AD_InfoRelated;
import org.compiere.util.Env;
import org.idempiere.cache.ImmutablePOSupport;
public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn {
public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn, ImmutablePOSupport {
/**
*
*/
private static final long serialVersionUID = -6216174103510277333L;
private static final long serialVersionUID = 4000783886138460291L;
public MInfoRelated(Properties ctx, int AD_InfoRelated_ID, String trxName) {
super(ctx, AD_InfoRelated_ID, trxName);
@ -78,5 +79,15 @@ public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn {
public MInfoColumn getAD_InfoColumn (){
return (MInfoColumn) getParentRelatedColumn();
}
@Override
public MInfoRelated markImmutable() {
if (is_Immutable())
return this;
makeImmutable();
return this;
}
}

View File

@ -83,7 +83,7 @@ public class GridWindow implements Serializable
public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID, boolean virtual)
{
if (log.isLoggable(Level.CONFIG)) log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID);
GridWindowVO mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID);
GridWindowVO mWindowVO = GridWindowVO.get (AD_Window_ID, WindowNo);
if (mWindowVO == null)
return null;
return new GridWindow(mWindowVO, virtual);

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
import org.compiere.util.CCache;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
@ -40,7 +41,51 @@ public class GridWindowVO implements Serializable
*
*/
private static final long serialVersionUID = 6884332743173214735L;
private static final CLogger log = CLogger.getCLogger(GridWindowVO.class);
/** Window Cache */
private static CCache<Integer,GridWindowVO> s_windowsvo
= new CCache<Integer,GridWindowVO>(I_AD_Window.Table_Name, I_AD_Window.Table_Name+"|GridWindowVO", 10);
/**
*
* @param AD_Window_ID
* @param windowNo
* @return {@link GridWindowVO}
*/
public static GridWindowVO get(int AD_Window_ID, int windowNo)
{
return get(AD_Window_ID, windowNo, -1);
}
/**
*
* @param AD_Window_ID
* @param windowNo
* @param AD_Menu_ID
* @return {@link GridWindowVO}
*/
public static GridWindowVO get(int AD_Window_ID, int windowNo, int AD_Menu_ID)
{
GridWindowVO mWindowVO = s_windowsvo.get(AD_Window_ID);
if (mWindowVO != null)
{
mWindowVO = mWindowVO.clone(windowNo);
if (log.isLoggable(Level.INFO)) log.info("Cached=" + mWindowVO);
}
if (mWindowVO == null)
{
if (log.isLoggable(Level.CONFIG)) log.config("create local");
mWindowVO = GridWindowVO.create (Env.getCtx(), windowNo, AD_Window_ID, AD_Menu_ID);
if (mWindowVO != null)
{
s_windowsvo.put(AD_Window_ID, mWindowVO);
}
}
return mWindowVO;
}
/**
* Create Window Value Object
* @param WindowNo window no for ctx
@ -120,60 +165,34 @@ public class GridWindowVO implements Serializable
// -- Get Window
StringBuilder sql = new StringBuilder("SELECT Name,Description,Help,WindowType, "
+ "AD_Color_ID,AD_Image_ID,WinHeight,WinWidth, "
+ "IsSOTrx, AD_Window_UU ");
if (Env.isBaseLanguage(vo.ctx, "AD_Window"))
sql.append("FROM AD_Window w WHERE w.AD_Window_ID=? AND w.IsActive='Y'");
MWindow window = MWindow.get(AD_Window_ID);
boolean base = Env.isBaseLanguage(vo.ctx, "AD_Window");
if (window != null)
{
vo.Name = base ? window.getName() : window.get_Translation(MWindow.COLUMNNAME_Name);
vo.Description = base ? window.getDescription() : window.get_Translation(MWindow.COLUMNNAME_Description);
if (vo.Description == null)
vo.Description = "";
vo.Help = base ? window.getHelp() : window.get_Translation(MWindow.COLUMNNAME_Help);
if (vo.Help == null)
vo.Help = "";
vo.WindowType = window.getWindowType();
//
vo.AD_Color_ID = window.getAD_Color_ID();
vo.AD_Image_ID = window.getAD_Image_ID();
//vo.IsReadWrite = rs.getString(7);
//
vo.WinHeight = window.getWinHeight();
vo.WinWidth = window.getWinWidth();
//
vo.IsSOTrx = window.isSOTrx();
vo.AD_Window_UU = window.getAD_Window_UU();
}
else
sql.append("FROM AD_Window_vt w WHERE w.AD_Window_ID=?")
.append(" AND AD_Language='")
.append(Env.getAD_Language(vo.ctx)).append("'");
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
// create statement
pstmt = DB.prepareStatement(sql.toString(), null);
pstmt.setInt(1, vo.AD_Window_ID);
// get data
rs = pstmt.executeQuery();
if (rs.next())
{
vo.Name = rs.getString(1);
vo.Description = rs.getString(2);
if (vo.Description == null)
vo.Description = "";
vo.Help = rs.getString(3);
if (vo.Help == null)
vo.Help = "";
vo.WindowType = rs.getString(4);
//
vo.AD_Color_ID = rs.getInt(5);
vo.AD_Image_ID = rs.getInt(6);
//vo.IsReadWrite = rs.getString(7);
//
vo.WinHeight = rs.getInt(7);
vo.WinWidth = rs.getInt(8);
//
vo.IsSOTrx = "Y".equals(rs.getString(9));
vo.AD_Window_UU = rs.getString(10);
}
else
vo = null;
}
catch (SQLException ex)
{
CLogger.get().log(Level.SEVERE, sql.toString(), ex);
return null;
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
vo = null;
}
// Ensure ASP exceptions
MRole role = MRole.getDefault(ctx, false);
final Boolean windowAccess = vo!=null ? role.getWindowAccess(vo.AD_Window_ID) : null;
@ -184,7 +203,7 @@ public class GridWindowVO implements Serializable
if (vo == null)
{
CLogger.get().log(Level.SEVERE, "No Window - AD_Window_ID=" + AD_Window_ID
+ ", AD_Role_ID=" + role + " - " + sql);
+ ", AD_Role_ID=" + role);
CLogger.get().saveError("AccessTableNoView", "(Not found)");
return null;
}

View File

@ -29,6 +29,7 @@ import org.compiere.util.Evaluatee;
import org.compiere.util.Evaluator;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.idempiere.cache.ImmutablePOSupport;
/**
* Info Window Column Model
@ -36,12 +37,12 @@ import org.compiere.util.Util;
* @author Jorg Janke
* @version $Id: MInfoColumn.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $
*/
public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn
public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn, ImmutablePOSupport
{
/**
*
*/
private static final long serialVersionUID = -6313260451237775302L;
private static final long serialVersionUID = 3909164419255524834L;
/**
* Stanfard Constructor
@ -226,4 +227,16 @@ public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn
public I_AD_Val_Rule getAD_Val_Rule() throws RuntimeException {
return MValRule.getCopy(getCtx(), getAD_Val_Rule_ID(), get_TrxName());
}
@Override
public PO markImmutable() {
if (is_Immutable())
return this;
makeImmutable();
if (m_parent != null && !m_parent.is_Immutable())
m_parent.markImmutable();
return this;
}
} // MInfoColumn

View File

@ -33,6 +33,9 @@ import org.compiere.model.AccessSqlParser.TableInfo;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.idempiere.cache.ImmutableIntPOCache;
import org.idempiere.cache.ImmutablePOSupport;
/**
* Info Window Model
@ -40,13 +43,16 @@ import org.compiere.util.Msg;
* @author Jorg Janke
* @version $Id: MInfoWindow.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $
*/
public class MInfoWindow extends X_AD_InfoWindow
public class MInfoWindow extends X_AD_InfoWindow implements ImmutablePOSupport
{
/**
*
*/
private static final long serialVersionUID = -1619434756919905441L;
private static final long serialVersionUID = 6723480469706009814L;
/** Cache */
private static ImmutableIntPOCache<Integer,MInfoWindow> s_cache = new ImmutableIntPOCache<Integer,MInfoWindow>(Table_Name, 20);
/**
* Standard Constructor
* @param ctx context
@ -75,7 +81,16 @@ public class MInfoWindow extends X_AD_InfoWindow
*/
public MInfoWindow(MInfoWindow copy)
{
this(Env.getCtx(), 0, (String)null);
this(copy, (String) null);
}
/**
* Copy constructor
* @param copy
*/
public MInfoWindow(MInfoWindow copy, String trxName)
{
this(Env.getCtx(), 0, trxName);
copyPO(copy);
this.m_validateEachColumn = copy.m_validateEachColumn;
this.m_infocolumns = copy.m_infocolumns != null ? Arrays.stream(copy.m_infocolumns).map(MInfoColumn::new).toArray(MInfoColumn[]::new) : null;
@ -105,18 +120,23 @@ public class MInfoWindow extends X_AD_InfoWindow
/**
* @author xolali
* @param AD_InfoWindow_ID
* @return
* @return {@link MInfoWindow}
*/
public static MInfoWindow getInfoWindow(int AD_InfoWindow_ID) {
if (AD_InfoWindow_ID != 0) {
MInfoWindow infoWin = (MInfoWindow)new Query(Env.getCtx(), Table_Name, "AD_InfoWindow_ID=?", null)
if (AD_InfoWindow_ID > 0) {
Integer key = Integer.valueOf(AD_InfoWindow_ID);
MInfoWindow infoWin = s_cache.get(key);
if (infoWin != null)
return infoWin;
infoWin = (MInfoWindow)new Query(Env.getCtx(), Table_Name, "AD_InfoWindow_ID=?", null)
.setParameters(AD_InfoWindow_ID)
.first();
if (infoWin != null)
if (infoWin != null) {
s_cache.put(key, infoWin);
return infoWin;
}
}
return null;
@ -195,12 +215,19 @@ public class MInfoWindow extends X_AD_InfoWindow
}
/** return true if the current role can access to the specified info window ; otherwise return null */
/**
* @param infoWindowID
* @param trxName
* return MInfoWindow if the current role can access to the specified info window ; otherwise return null
* */
public static MInfoWindow get(int infoWindowID, String trxName) {
MInfoWindow iw = new MInfoWindow(Env.getCtx(), infoWindowID, null);
MInfoWindow iw = getInfoWindow(infoWindowID);
Boolean access = MRole.getDefault().getInfoAccess(iw.getAD_InfoWindow_ID());
if (access != null && access.booleanValue())
if (access != null && access.booleanValue()) {
if (!Util.isEmpty(trxName, true))
iw = new MInfoWindow(iw, trxName);
return iw;
}
return null;
}
@ -471,6 +498,25 @@ public class MInfoWindow extends X_AD_InfoWindow
boolean isValidateEachColumn() {
return m_validateEachColumn;
}
@Override
public MInfoWindow markImmutable() {
if (is_Immutable())
return this;
makeImmutable();
if (m_infocolumns != null && m_infocolumns.length > 0)
Arrays.stream(m_infocolumns).forEach(e -> e.markImmutable());
if (m_infoProcess != null && m_infoProcess.length > 0)
Arrays.stream(m_infoProcess).forEach(e -> e.markImmutable());
if (m_infoRelated != null && m_infoRelated.length > 0)
Arrays.stream(m_infoRelated).forEach(e -> e.markImmutable());
return this;
}
@Override
public I_AD_Table getAD_Table() throws RuntimeException {
return MTable.get(Env.getCtx(), getAD_Table_ID(), get_TrxName());
}
} // MInfoWindow

View File

@ -29,7 +29,6 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
@ -47,7 +46,6 @@ import org.adempiere.util.ServerContextProvider;
import org.compiere.Adempiere;
import org.compiere.db.CConnection;
import org.compiere.model.GridWindowVO;
import org.compiere.model.I_AD_Window;
import org.compiere.model.MClient;
import org.compiere.model.MColumn;
import org.compiere.model.MLookupCache;
@ -1922,10 +1920,6 @@ public final class Env
return p;
}
/** Window Cache */
private static CCache<Integer,GridWindowVO> s_windowsvo
= new CCache<Integer,GridWindowVO>(I_AD_Window.Table_Name, I_AD_Window.Table_Name+"|GridWindowVO", 10);
/**
* Get Window Model
*
@ -1937,46 +1931,10 @@ public final class Env
public static GridWindowVO getMWindowVO (int WindowNo, int AD_Window_ID, int AD_Menu_ID)
{
if (log.isLoggable(Level.CONFIG)) log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID);
GridWindowVO mWindowVO = null;
if (AD_Window_ID != 0 && Ini.isCacheWindow()) // try cache
{
mWindowVO = s_windowsvo.get(AD_Window_ID);
if (mWindowVO != null)
{
mWindowVO = mWindowVO.clone(WindowNo);
if (log.isLoggable(Level.INFO)) log.info("Cached=" + mWindowVO);
}
}
// Create Window Model on Client
if (mWindowVO == null)
{
if (log.isLoggable(Level.CONFIG)) log.config("create local");
mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID, AD_Menu_ID);
if (mWindowVO != null)
s_windowsvo.put(AD_Window_ID, mWindowVO);
} // from Client
GridWindowVO mWindowVO = GridWindowVO.get(AD_Window_ID, WindowNo, AD_Menu_ID);
if (mWindowVO == null)
return null;
// Check (remote) context
if (!mWindowVO.ctx.equals(Env.getCtx()))
{
// Remote Context is called by value, not reference
// Add Window properties to context
Enumeration<?> keyEnum = mWindowVO.ctx.keys();
while (keyEnum.hasMoreElements())
{
String key = (String)keyEnum.nextElement();
if (key.startsWith(WindowNo+"|"))
{
String value = mWindowVO.ctx.getProperty (key);
Env.setContext(Env.getCtx(), key, value);
}
}
// Sync Context
mWindowVO.setCtx(Env.getCtx());
}
return mWindowVO;
} // getWindow

View File

@ -189,7 +189,7 @@ public class DefaultInfoFactory implements IInfoFactory {
@Override
public InfoWindow create(int AD_InfoWindow_ID, String predefinedContextVariables) {
MInfoWindow infoWindow = new MInfoWindow(Env.getCtx(), AD_InfoWindow_ID, (String)null);
MInfoWindow infoWindow = MInfoWindow.getInfoWindow(AD_InfoWindow_ID);
String tableName = infoWindow.getAD_Table().getTableName();
String keyColumn = tableName + "_ID";
InfoPanel info = create(-1, tableName, keyColumn, null, false, null, AD_InfoWindow_ID, false, predefinedContextVariables);

View File

@ -584,7 +584,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
@Override
protected void loadInfoWindowData (){
if (m_infoWindowID > 0) {
infoWindow = new MInfoWindow(Env.getCtx(), m_infoWindowID, null);
infoWindow = MInfoWindow.getInfoWindow(m_infoWindowID);
}else {
infoWindow = MInfoWindow.get(p_tableName, (String)null);
}

View File

@ -427,7 +427,7 @@ public class HelpController
}
else if (ctxType.equals(X_AD_CtxHelp.CTXTYPE_Info))
{
MInfoWindow info = new MInfoWindow(Env.getCtx(), recordId, null);
MInfoWindow info = MInfoWindow.getInfoWindow(recordId);
// Load User Def
MUserDefInfo userDef = MUserDefInfo.getBestMatch(Env.getCtx(), info.getAD_InfoWindow_ID());

View File

@ -1943,29 +1943,11 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
if (m_SO_Window_ID > 0)
return m_SO_Window_ID;
//
String sql = "SELECT AD_Window_ID, PO_Window_ID FROM AD_Table WHERE TableName=?";
PreparedStatement pstmt = null;
ResultSet rs = null;
try
MTable table = MTable.get(Env.getCtx(), tableName);
if (table != null)
{
pstmt = DB.prepareStatement(sql, null);
pstmt.setString(1, tableName);
rs = pstmt.executeQuery();
if (rs.next())
{
m_SO_Window_ID = rs.getInt(1);
m_PO_Window_ID = rs.getInt(2);
}
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null;
pstmt = null;
m_SO_Window_ID = table.getAD_Window_ID();
m_PO_Window_ID = table.getPO_Window_ID();
}
//
if (!isSOTrx && m_PO_Window_ID > 0)