1

コレクションをハッシュマップとして取得する外側の繰り返しコントロールがあります(変数名はhmOuterCollectionです)。この繰り返しコントロール内には、コレクションをハッシュマップ (変数名は hmInnerCollection) として取得する別の繰り返しコントロールがあります。内側の繰り返しコントロール コレクションは、外側の繰り返しエントリのキーに基づいています。何が起こるかというと、外側のリピート エントリをクリックすると、内側のリピート コントロール エントリが以前のエントリを上書きするように見えます。

たとえば、次のことを考慮してください。

Barcelona (外側のエントリ、最初にクリック)
Messi
Xavi
Puyol
マンチェスター・ユナイテッド(外側のエントリ、2 番目にクリック)
Rooney,
xxx
Real Madrid (外側のエントリ、3 番目にクリック)
Ronaldo
Kaka

これらのサッカー チームをすべて展開した後、戻って Messi という名前の選手をクリックします。サーバー コンソールに Ronaldo という名前が表示されます。Xavi という名前をクリックすると、Kaka が表示されます。

ここで何が起こっているのかわかりません。「repeatControls」および「removeRepeat」プロパティも試しました。運がない。これは Java ハッシュマップのキャッシングですか、それとも繰り返し制御の動作に問題がありますか。

誰かアイデアがあれば教えてください。

XPageのソースはこちら

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
    <xp:script src="/xpTestCacheIssue.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:repeat id="repeat1" rows="30" value="#{javascript:getTeams()}"
    var="entryTeam">
    <xp:panel>
        <xp:link escape="true"
            text="#{javascript:entryTeam.getValue()}" id="lnkTeam">
            <xp:eventHandler event="onclick" submit="true"
                refreshMode="partial" refreshId="panelPlayers"
                action="#{javascript:viewScope.teamID=entryTeam.getKey()}">
            </xp:eventHandler>
        </xp:link>
    </xp:panel>
    <xp:panel id="panelPlayers">
        <xp:repeat id="repeat2" rows="30"
            value="#{javascript:getPlayers(viewScope.teamID)}"
            var="entryPlayer">
            <xp:panel style="margin-left:20px;padding:10px">
                <xp:link escape="true"
                    text="#{javascript:entryPlayer.getValue()}" id="lnkPlayer">
                    <xp:eventHandler event="onclick" submit="true"
                        refreshMode="partial" refreshId="selectedPlayer"
                        execMode="partial" execId="lnkPlayer">
                        <xp:this.action><![CDATA[#{javascript:viewScope.PlayerName=entryPlayer.getValue();}]]></xp:this.action>
                    </xp:eventHandler>
                </xp:link>
            </xp:panel>
        </xp:repeat>
    </xp:panel>
</xp:repeat>
<xp:panel id="selectedPlayer" style="border:1px solid green;padding:20px;background-color:yellow;font-weight:bold">
    <xp:text escape="true" id="computedField1"
        value="#{javascript:viewScope.PlayerName}">
    </xp:text>
</xp:panel>

これらの繰り返しのハッシュマップを取得する Java コードを次に示します。Java メソッドを呼び出す SSJS 関数があります。

    public Map<String,String> getSoccerTeams() {
    Map<String,String> hmTeams=new HashMap<String,String>();
    try {
        ViewEntryCollection vec=vwTeams.getAllEntries();
        ViewEntry ve=vec.getFirstEntry();
        while (ve!=null) {
            hmTeams.put(ve.getUniversalID(), ve.getDocument().getItemValueString("TeamName"));
            ve=vec.getNextEntry(ve);
        }               
    } catch (Exception e) {
        e.printStackTrace();
    }
    return hmTeams;
}   
public Map<String,String> getPlayers(String idPlayer) {
    HashMap<String,String> hmPlayers=new HashMap<String,String>();
    try {
        View vwPlayers=this.dbCur.getView("playersview");
        DocumentCollection dc=vwPlayers.getAllDocumentsByKey(idPlayer, true);
        Document doc=dc.getFirstDocument();
        while (doc!=null) {
            hmPlayers.put(doc.getUniversalID(), doc.getItemValueString("PlayerName"));
            doc=dc.getNextDocument(doc);
        }               
    } catch (Exception e) {
        e.printStackTrace();
    }
    return hmPlayers;
}   

Java メソッドを呼び出す SSJS コードを次に示します。

function getTeams() {
    var Teams=new LoadTeams();
    var hmTeams=Teams.getSoccerTeams();
    return hmTeams.entrySet();  
}

function getPlayers(playerID) {
    var Teams=new LoadTeams();
    var hmPlayers=Teams.getPlayers(playerID);
    return hmPlayers.entrySet();    
}
4

1 に答える 1

3

あなたの問題はここにあります:

 value="#{javascript:getPlayers(viewScope.teamID)}"

次のように読む必要があります。

 value="#{javascript:getPlayers(entryTeam.getKey())}"

外側の変数は内側の繰り返しで使用できます。コードをスコープ オブジェクトに詰め込むと、そこにある最後の値が参照されます。

そして、Java コードで Notes オブジェクトをリサイクルしてください。また、Bean に値をキャッシュして、毎回ビューを読み取る必要がないようにすることもできます。最後に、コードから SSJS を削除し、EL だけを使用することができます -> さらに高速に

ELについて:

Java クラスが次の代わりに記述できるManagedBean " Soccer " として登録されていると仮定しましょう。

     <xp:repeat id="repeat1" rows="30" value="#{javascript:getTeams()}"
var="entryTeam">

これです:

 <xp:repeat id="repeat1" rows="30" value="#{Soccer.teams}"
var="entryTeam">

そして代わりに:

   <xp:repeat id="repeat2" rows="30"
        value="#{javascript:getPlayers(entryTeam.getKey())}"
        var="entryPlayer">

あなたが書く:

  <xp:repeat id="repeat2" rows="30"
        value="#{Soccer.teams[entryTeam.key]}"
        var="entryPlayer">

EL は Maps を処理できるため、実際には関数のみが必要であり、getTeams()関数は必要ありませgetPlayers()ん。ビューを何度も読み取らないように、Java クラスを少し調整します。

        public class SoccerHandler {

private Map<String,Collection<String>> allTheTeams = null;

public Map<String,String> getTeams() {
    if (allTheTeams == null) {
        this.loadTheTeams();
    }
    return allTheTeams;
}

private void loadTheTeams() {
    // Add your own try/catch
    this.allTheTeams = new HashMap<String,Collection<String>>();
    View vwPlayers=this.getPlayersView(); // <-- Don't keep Notes objects in a BEAN
    ViewEntryCollection vec=vwPlayers.getAllEntries();
    String lastTeamName = "";
    Collection<String> curTeam = null;
    ViewEntry ve=vec.getFirstEntry();
    while (ve!=null) {
        Vector colVals = ve.getColumnValues();
        String curTeamName = colVals.get(0); // 1st column = team
        String curPlayerName = colVals.get(1); // 2nd column = player
        if (!curTeamName.equals(lastTeamName)) { // New team found
            if (curTeam != null) {
                this.allTheTeams.put(lastTeamName, curTeam);
            }
            curTeam = new ArrayList<String>();
            lastTeamName = curTeamName;
        }
        curTeam.put(curPlayerName);
        ve=vec.getNextEntry(ve);
    }
    // Make sure we don't miss the last team
    if (curTeam != null) {
        this.allTheTeams.put(lastTeamName, curTeam);
    }   
    ve.recycle();
    vec.recyle();
}

// If you want to be able to force a re-read
public void reset() {
    this.allTheTeams = null;
}
// more code here like getPlayerView that uses the resolver
}

それが役立つことを願っています

于 2012-05-11T04:53:58.913 に答える