tutorials.de Buch-Aktion 05/2012
Seite 3 von 4 ErsteErste 1234 LetzteLetzte
ERLEDIGT
NEIN
ANTWORTEN
48
ZUGRIFFE
11133
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #31
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    Zitat Zitat von limago Beitrag anzeigen
    Hi,

    Es sind keine Pakete von J2EE dabei. Eine Record-Klasse kannst Du leicht selbst schreiben. Sie kapselt den Zugriff auf die Datenbank.

    Ich würde stattdessen eher eine Tableklasse schreiben, mit den einzelnen Methoden

    int getColumnCount();
    String getValue(int column);
    String getValue(String columnName);
    String getColumnName(int column);
    long getRowCount();
    boolean moveToRow(long row);

    oder meinetwegen auch

    String valueAt(long row, int column);

    Den SelectString kann man schon bei der Konstruktion mitgeben. Das Paging-Model bedient sich dann aus dieser Klasse ( die am besten Ihrerseits die Zeilen puffert). Die Klasse "ArrowIcon" ist nur zum malen auf die Buttons da.

    Habe leider etwas Stress, sonst würde ich mal eine Lösung schreiben. Vielleicht nächste Woche.

    Gruß
    Danke nochmal für deine Mühe. Bei meiner Lösung habe ich die Tableklasse so implementiert, dass Sie alle Daten in ein Array reinschreibt. Auf diese Art und Weise, kann ich mir zwar sehr viel größere Tabellen anzeigen lassen, als innerhalb einer einzigen ScrollPane aber bei wirklich großen Tabellen hab ich natürlich immernoch das Speicherproblem. Meine Frage ist wie kann ich die Methoden boolean moveToRow(long row); und String valueAt(long row, int column); ohne scrollable Resultsets implementieren?
     

  2. #32
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Aus aktuellem Anlass (Nachfrage) führe ich diesen Thread weiter...

    Zum Problem:

    Ich hatte Dir ein SQL-Beispiel gepostet, mit dem Du die Daten "päckchenweise" aus der Datenbank auslesen kannst. Wenn Du gemäß meines Beispiels im SQL-Statement Zeilennummern erzeugst, kannst Du mit einer einfachen Abfrage jeweils so viele Datensätze lesen, wie Du verarbeiten kannst.

    Hier nochmal der SQLString:

    SELECT emp_id, lname, fname, job_id,
    (SELECT COUNT(*) FROM employee e2 WHERE e2.lname <= e.lname AND e2.job_id = 10) AS rownumber
    FROM employee e
    WHERE job_id = 10
    ORDER BY lname


    Der Unterselect "(SELECT COUNT(*) FROM employee e2 WHERE e2.lname <= e.lname AND e2.job_id = 10) AS rownumber" erzeugt eine Zeilennummer.

    Mache daraus einen View (Abfrage), dann kannst du einen Select auf den view Ausführen, hast aber immer zeilennummern in der Abfrage.

    Dadurch kannst du mit
    Select * from MyView where rownumber between x and y

    die Daten paketweise lesen. Also nicht alle Daten auf einmal in ein Array packen, sondern das TableModel (oder wer auch immer) lädt bei Bedarf immer nur wenige hundert Zeilen über diesen View ein. damit können Deine Tabellen Terrabyte groß sein, Du liest nur was Du brauchst...

    Gruß
     
    I didn't write this; a very complex macro did.

  3. #33
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    Vielen Dank für Deine Antwort!

    Mein Problem ist leider, dass der User meines ies die DB zur Laufzeit auswählt und auch SQL-Statements zur Laufzeit eingeben können soll. Von diesen Statements brauche ich denn das Ergebnis innerhalb meiner JTable, deshalb kann ich keine Views anlegen, weil ich eben vorher nicht weis wie die entsprechende DB aussieht.
    Ich könnte höchstens versuchen die Strings mit den SQL-Statements auseinander zu nehmen und automatisch ein Feld mit der Zeilennummer in diese Statements einzufügen, aber allein schon bei dem Gedanken daran wird mir schlecht
     

  4. #34
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Hi,

    wenn ich mal mehr Zeit habe, werde ich dem dem Problem mal näher widmen. Aaaaber andere Leute haben das Problem ja auch. In der Regel wird es dadurch gelöst, dass man erst einen Select count(*) auf die where -Klausel los läßt, dann beim Überschreiten einer Schwelle den Anwender zur Präzessierung der Auswahl auffordert.

    Ist es möglich mehr über die Hintergründe zu erfahren? Möglicherweise, kann man das Problem ja an einer ganz anderen Stelle lösen.

    Meine Neugier ist geweckt.

    Grüße
     
    I didn't write this; a very complex macro did.

  5. #35
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    Also... ich hab mich dann mal entschlossen für verschiedene DBMSs verschiedene PagingModels zu schreiben.

    hier einmal das zu MSSQL geht auch mit Oracle:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
     
    import javax.swing.table.*;
    import javax.swing.*;
    import java.awt.event.*;
     
    public class MSSQLPagingModel extends AbstractTableModel
    {
        private Connection conn;
        private ResultSet rs;
        private ResultSetMetaData rsmd;
        private String statement;
        
        protected int pageSize;
        protected int pageOffset;
        private int row;
        private int rowCount;
        private int columnCount;
        private String[] columnNames;
        protected String[][] data;
     
        public MSSQLPagingModel(String statement)
        {
            this.statement = statement;
            conn = DBConnection.getConnection();
            row = 0;
            pageOffset = 0;
            pageSize = 100;
            try 
            {
                rs = DBConnection.executeQuery(statement);
                rsmd = rs.getMetaData();
                //Zeilenzahl berechnen
                rs.last();
                rowCount = rs.getRow();
                rs.beforeFirst();
                //////
                columnCount = rsmd.getColumnCount();
                columnNames = new String[columnCount];
                for (int i=0; i<columnCount; i++)
                {
                    columnNames[i] = rsmd.getColumnName(i+1);
                }
                data = new String[pageSize][columnCount];
                int i=0;
                while (rs.next() && i<pageSize)
                {
                    for (int j=0; j<columnCount; j++)
                    {
                        data[i][j]= rs.getString(j+1);                  
                    }
                    i++;
                }
                rs.close();
            }
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
     
        //Return values appropriate for the visible table part.
        public int getRowCount() { return Math.min(pageSize, rowCount); }
        public int getColumnCount() { return columnCount; }
     
        // Work only on the visible part of the table.
        public Object getValueAt(int row, int col) 
        {
         return data[row][col];
        }
        public String getColumnName(int col) 
        {
         return columnNames[col];
        }
        //Use this method to figure out which page you are on.
        public int getPageOffset() { return pageOffset; }
     
        public int getPageCount() 
        { 
         return (int)Math.ceil((double)rowCount / pageSize);
        }
     
        // Use this method if you want to know how big the real table is . . . we
        // could also write "getRealValueAt()" if needed.
        public int getRealRowCount() 
        {
         return rowCount;
        }
     
        public int getPageSize() { return pageSize; }
        
        public void setPageSize(int s) 
        { 
         if (s == pageSize) { return; }
         int oldPageSize = pageSize;
         pageSize = s;
         pageOffset = (oldPageSize * pageOffset) / pageSize;
         fireTableDataChanged();
         if (pageSize < oldPageSize) 
         {
           fireTableRowsDeleted(pageSize, oldPageSize - 1);
         }
         else 
         {
           fireTableRowsInserted(oldPageSize, pageSize - 1);
         }
        }
     
        //Update the page offset and fire a data changed (all rows).
        public void pageDown() 
        {
         if (pageOffset < getPageCount() - 1) 
         {
           pageOffset++;
           //System.out.println(pageOffset);
           try 
           {
               rs = DBConnection.executeQuery(statement);
               rs.first();
               rs.relative((pageOffset*pageSize)-1);
               int i=0;
               while (rs.next() && i<pageSize)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
               //letzte Seite mit leerzeichen füllen
               for (int k=i; k<pageSize; k++)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[k][j] = "";
                   }
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   Update the page offset and fire a data changed (all rows).
        public void pageUp() 
        {
         if (pageOffset > 0) 
         {
           pageOffset--;
           //System.out.println(pageOffset);
           try 
           {
               rs = DBConnection.executeQuery(statement);
               rs.first();
               rs.relative((pageOffset*pageSize)-1);
               //System.out.println(test);
               int i=0;
               while (rs.next() && i<pageSize)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   We provide our own version of a scrollpane that includes
    //   the page up and page down buttons by default.
        public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
        {
         JScrollPane jsp = new JScrollPane(jt);
         TableModel tmodel = jt.getModel();
         
         // Don't choke if this is called on a regular table . . .
         if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof MSSQLPagingModel || tmodel instanceof PagingModel)) 
         {
           return jsp;
         }
     
         // Okay, go ahead and build the real scrollpane
         final MSSQLPagingModel model = (MSSQLPagingModel)tmodel;
         final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
         upButton.setEnabled(false);  // starts off at 0, so can't go up
         final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
         if (model.getPageCount() <= 1) 
         {
           downButton.setEnabled(false);  // One page...can't scroll down
         }
     
         upButton.addActionListener(new ActionListener() 
         {
           public void actionPerformed(ActionEvent ae) 
           {
             model.pageUp();
     
             // If we hit the top of the data, disable the up button.
             if (model.getPageOffset() == 0) 
             {
               upButton.setEnabled(false);
             }
             downButton.setEnabled(true);
           }
         } );
     
         downButton.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
             model.pageDown();
     
             // If we hit the bottom of the data, disable the down button.
             if (model.getPageOffset() == (model.getPageCount() - 1)) {
               downButton.setEnabled(false);
             }
             upButton.setEnabled(true);
           }
         } );
     
         // Turn on the scrollbars; otherwise we won't get our corners.
         jsp.setVerticalScrollBarPolicy
             (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         jsp.setHorizontalScrollBarPolicy
             (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
     
         // Add in the corners (page up/down).
         jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
         jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);
     
         return jsp;
        }
    }

    Der obige code funktioniert leider nicht mit MySQL. Da kommt immernoch dieser Speichererror. Also hab ich für MySQL ein eigenes PageingModel geschrieben:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
     
    import javax.swing.table.*;
    import javax.swing.*;
    import java.awt.event.*;
     
    public class MySQLPagingModel extends AbstractTableModel
    {
        private Connection conn;
        private ResultSet rs;
        private ResultSetMetaData rsmd;
        private String statement;
        
        protected int pageSize;
        protected int pageOffset;
        private int row;
        private int rowCount;
        private int columnCount;
        private String[] columnNames;
        protected String[][] data;
     
        public MySQLPagingModel(String statement)
        {
            this.statement = statement;
            conn = DBConnection.getConnection();
            row = 0;
            pageOffset = 0;
            pageSize = 100;
            try 
            {
                rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
                rsmd = rs.getMetaData();
                //Zeilenzahl berechnen
                Statement stm2 = conn.createStatement();
                ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
                rs2.next();
                rowCount = rs2.getInt(1);
                rs2.close();
                stm2.close();
                //////
                columnCount = rsmd.getColumnCount();
                columnNames = new String[columnCount];
                for (int i=0; i<columnCount; i++)
                {
                    columnNames[i] = rsmd.getColumnName(i+1);
                }
                data = new String[pageSize][columnCount];
                int i=0;
                while (rs.next())
                {
                    for (int j=0; j<columnCount; j++)
                    {
                        data[i][j]= rs.getString(j+1);                  
                    }
                    i++;
                }
                rs.close();
            }
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
     
        //Return values appropriate for the visible table part.
        public int getRowCount() { return Math.min(pageSize, rowCount); }
        public int getColumnCount() { return columnCount; }
     
        // Work only on the visible part of the table.
        public Object getValueAt(int row, int col) 
        {
         //int realRow = row + (pageOffset * pageSize);
         return data[row][col];
        }
        public String getColumnName(int col) 
        {
         return columnNames[col];
        }
        //Use this method to figure out which page you are on.
        public int getPageOffset() { return pageOffset; }
     
        public int getPageCount() 
        { 
         return (int)Math.ceil((double)rowCount / pageSize);
        }
     
        // Use this method if you want to know how big the real table is . . . we
        // could also write "getRealValueAt()" if needed.
        public int getRealRowCount() 
        {
         return rowCount;
        }
     
        public int getPageSize() { return pageSize; }
        /*
        public void setPageSize(int s) 
        { 
         if (s == pageSize) { return; }
         int oldPageSize = pageSize;
         pageSize = s;
         pageOffset = (oldPageSize * pageOffset) / pageSize;
         fireTableDataChanged();
        */
        /*
         if (pageSize < oldPageSize) {
           fireTableRowsDeleted(pageSize, oldPageSize - 1);
         }
         else {
           fireTableRowsInserted(oldPageSize, pageSize - 1);
         }
        */
        //}
     
        //Update the page offset and fire a data changed (all rows).
        public void pageDown() 
        {
         System.out.println(pageOffset);
         if (pageOffset < getPageCount() - 1) 
         {
           pageOffset++;
           try 
           {
               rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize);
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
               for (int k=i; k<pageSize; k++)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[k][j] = "";
                   }
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   Update the page offset and fire a data changed (all rows).
        public void pageUp() 
        {
         System.out.println(pageOffset);
         if (pageOffset > 0) 
         {
           pageOffset--;
           try 
           {
               String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
               rs = DBConnection.executeQuery(test);
               System.out.println(test);
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   We provide our own version of a scrollpane that includes
    //   the page up and page down buttons by default.
        public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
        {
         JScrollPane jsp = new JScrollPane(jt);
         TableModel tmodel = jt.getModel();
         
         // Don't choke if this is called on a regular table . . .
         if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
         {
           return jsp;
         }
     
         // Okay, go ahead and build the real scrollpane
         final MySQLPagingModel model = (MySQLPagingModel)tmodel;
         final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
         upButton.setEnabled(false);  // starts off at 0, so can't go up
         final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
         if (model.getPageCount() <= 1) 
         {
           downButton.setEnabled(false);  // One page...can't scroll down
         }
     
         upButton.addActionListener(new ActionListener() 
         {
           public void actionPerformed(ActionEvent ae) 
           {
             model.pageUp();
     
             // If we hit the top of the data, disable the up button.
             if (model.getPageOffset() == 0) 
             {
               upButton.setEnabled(false);
             }
             downButton.setEnabled(true);
           }
         } );
     
         downButton.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
             model.pageDown();
     
             // If we hit the bottom of the data, disable the down button.
             if (model.getPageOffset() == (model.getPageCount() - 1)) {
               downButton.setEnabled(false);
             }
             upButton.setEnabled(true);
           }
         } );
     
         // Turn on the scrollbars; otherwise we won't get our corners.
         jsp.setVerticalScrollBarPolicy
             (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         jsp.setHorizontalScrollBarPolicy
             (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
     
         // Add in the corners (page up/down).
         jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
         jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);
     
         return jsp;
        }
    }

    So das funktioniert zwar Theoretisch. Aber jeder Pagewechsel dauert ewig (so 30 - 45 sec) bei einer PageSize von 100. Irgendwie scheint der MySQL-Server die ergebnisse aber zu cachen oder irgendwelche temporären StoredProcedures anzulegen oder weiß der Geier. Auf jeden Fall geht das Angucken von Seiten, die ich schonmal angeguckt hab richtig schön schnell, auch wenn ich mein Prog zwischendurch schliesse und wieder neu öffne.

    Meine Frage wäre, wieso ist das so lahm? Wie kann ich das schneller machen?

    Und so aus mehr allgemeinem Interesse. Wie speichert der MySQL-Server welche Daten, dass ich so schnell darauf zugriff habe, wenn ich sie vorher schon irgendwann mal abgerufen habe? (Der kann ja nicht hunderte von Ergebnissmengen cachen oder etwa doch?)
     

  6. #36
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Hi,

    hier mal ein Schnellschuss aus der Hüfte... Ich würde die Statements, wenn es geht in PreparedStatements umwandeln. Dann werden Sie oft deutlich schneller ausgeführt.

    Soweit ich weiss, muss bei einem Statement immer der SQL-String von dem DBMS geparst und ein Ausführungsplan erstellt werden. Wenn Du Glück hast, wird das Statement danach gecached.

    Ein PreparedStatement macht das gleich und landet gleich im Cache. Es kann parametriesiert werden und sollte deswegen die Geschwindigkeit erhöhen...

    Versuchs mal.

    Gruss
     
    I didn't write this; a very complex macro did.

  7. #37
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    Logisch da hätt ich auch mal drauf kommen können.
    Aber, ich hab das jetzt gemacht und scheinbar scheinen preparedStatements in verbindung mit LIMIT nicht viel zu nützen. Denn jetzt hab ich ca. 15sec pro zu Ladender Seite. Allerding cacht der SQLServer jetzt nix mehr und so dauert der seitenaufbau immer 15sec.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
     
    import javax.swing.table.*;
    import javax.swing.*;
    import java.awt.event.*;
     
    public class MySQLPagingModel extends AbstractTableModel
    {
        private Connection conn;
        private PreparedStatement preparedStatement;
        private ResultSet rs;
        private ResultSetMetaData rsmd;
        private String statement;
        
        protected int pageSize;
        protected int pageOffset;
        private int row;
        private int rowCount;
        private int columnCount;
        private String[] columnNames;
        protected String[][] data;
     
        public MySQLPagingModel(String statement)
        {
            this.statement = statement;
            conn = DBConnection.getConnection();
            row = 0;
            pageOffset = 0;
            pageSize = 100;
            try 
            {
                preparedStatement = conn.prepareStatement("SELECT * FROM ("+statement+") AS tmp LIMIT ?, ?");
                rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
                rsmd = rs.getMetaData();
                //Zeilenzahl berechnen
                Statement stm2 = conn.createStatement();
                ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
                rs2.next();
                rowCount = rs2.getInt(1);
                rs2.close();
                stm2.close();
                //////
                columnCount = rsmd.getColumnCount();
                columnNames = new String[columnCount];
                for (int i=0; i<columnCount; i++)
                {
                    columnNames[i] = rsmd.getColumnName(i+1);
                }
                data = new String[pageSize][columnCount];
                int i=0;
                while (rs.next())
                {
                    for (int j=0; j<columnCount; j++)
                    {
                        data[i][j]= rs.getString(j+1);                  
                    }
                    i++;
                }
                rs.close();
            }
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
     
        //Return values appropriate for the visible table part.
        public int getRowCount() { return Math.min(pageSize, rowCount); }
        public int getColumnCount() { return columnCount; }
     
        // Work only on the visible part of the table.
        public Object getValueAt(int row, int col) 
        {
         return data[row][col];
        }
        public String getColumnName(int col) 
        {
         return columnNames[col];
        }
        //Use this method to figure out which page you are on.
        public int getPageOffset() { return pageOffset; }
     
        public int getPageCount() 
        { 
         return (int)Math.ceil((double)rowCount / pageSize);
        }
     
        // Use this method if you want to know how big the real table is . . . we
        // could also write "getRealValueAt()" if needed.
        public int getRealRowCount() 
        {
         return rowCount;
        }
     
        public int getPageSize() { return pageSize; }
        /*
        public void setPageSize(int s) 
        { 
         if (s == pageSize) { return; }
         int oldPageSize = pageSize;
         pageSize = s;
         pageOffset = (oldPageSize * pageOffset) / pageSize;
         fireTableDataChanged();
        */
        /*
         if (pageSize < oldPageSize) {
           fireTableRowsDeleted(pageSize, oldPageSize - 1);
         }
         else {
           fireTableRowsInserted(oldPageSize, pageSize - 1);
         }
        */
        //}
     
        //Update the page offset and fire a data changed (all rows).
        public void pageDown() 
        {
         System.out.println(pageOffset);
         if (pageOffset < getPageCount() - 1) 
         {
           pageOffset++;
           try 
           {
               preparedStatement.setInt(1, (pageOffset*pageSize));
               preparedStatement.setInt(2, pageSize);
               rs = preparedStatement.executeQuery();
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
               for (int k=i; k<pageSize; k++)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[k][j] = "";
                   }
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   Update the page offset and fire a data changed (all rows).
        public void pageUp() 
        {
         System.out.println(pageOffset);
         if (pageOffset > 0) 
         {
           pageOffset--;
           try 
           {
               //String test = statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize);
               //String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
               //rs = DBConnection.executeQuery(test);
               //System.out.println(test);
               preparedStatement.setInt(1, (pageOffset*pageSize));
               preparedStatement.setInt(2, pageSize);
               rs = preparedStatement.executeQuery();
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   We provide our own version of a scrollpane that includes
    //   the page up and page down buttons by default.
        public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
        {
         JScrollPane jsp = new JScrollPane(jt);
         TableModel tmodel = jt.getModel();
         
         // Don't choke if this is called on a regular table . . .
         if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
         {
           return jsp;
         }
     
         // Okay, go ahead and build the real scrollpane
         final MySQLPagingModel model = (MySQLPagingModel)tmodel;
         final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
         upButton.setEnabled(false);  // starts off at 0, so can't go up
         final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
         if (model.getPageCount() <= 1) 
         {
           downButton.setEnabled(false);  // One page...can't scroll down
         }
     
         upButton.addActionListener(new ActionListener() 
         {
           public void actionPerformed(ActionEvent ae) 
           {
             model.pageUp();
     
             // If we hit the top of the data, disable the up button.
             if (model.getPageOffset() == 0) 
             {
               upButton.setEnabled(false);
             }
             downButton.setEnabled(true);
           }
         } );
     
         downButton.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
             model.pageDown();
     
             // If we hit the bottom of the data, disable the down button.
             if (model.getPageOffset() == (model.getPageCount() - 1)) {
               downButton.setEnabled(false);
             }
             upButton.setEnabled(true);
           }
         } );
     
         // Turn on the scrollbars; otherwise we won't get our corners.
         jsp.setVerticalScrollBarPolicy
             (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         jsp.setHorizontalScrollBarPolicy
             (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
     
         // Add in the corners (page up/down).
         jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
         jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);
     
         return jsp;
        }
    }
     

  8. #38
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Hi,

    dann weiss ich auch nicht weiter. Hört sich so an, als müsstest Du tief in den MySql abtauchen und das hat mit Java nix mehr zu tun. Die 15 bzw. 30 Sekunden wundern mich ehrlich gesagt ein wenig. Hast Du das mal nativ mit der MySQL-Console validiert?

    Kannst Du die Daten denn nicht selbst cachen?

    Wie auch immer, wenn Du eine Lösung findest, wäre ich sehr interessiert...

    Gruß
     
    I didn't write this; a very complex macro did.

  9. #39
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    So, hab jez ne einigermaßen akzeptable Lösung gefunden.
    Hab statt "Select * From ("+statement+") as tmp LIMIT blabla.
    Einfach nur "("+statement+") Limit blabla" gemacht. Jetzt gehts schön schnell. Aber die letzte Page wird leider bis zur pageSize aufgefüllt.
    Wenn ich also z.B. (Select * From tabelle LIMIT 0, 150) LIMIT 0, 200; ausführe bekomme ich leider 200 ergebnisse und keine 150.
    Da das aber nur in der Anzeige so ist und zum Weiterverarbeiten das original Statement was der user eingegeben hat ausgeführt wird ist das jetzt nicht so wichtig.

    hier nochmal komplett:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.sql.Statement;
    //import java.util.List;
     
    import javax.swing.table.*;
    import javax.swing.*;
    import java.awt.event.*;
    //import java.awt.*;
     
    public class MySQLPagingModel extends AbstractTableModel
    {
        private Connection conn;
        private PreparedStatement preparedStatement;
        private ResultSet rs;
        private ResultSetMetaData rsmd;
        private String statement;
        
        protected int pageSize;
        protected int pageOffset;
        private int row;
        private int rowCount;
        private int columnCount;
        private String[] columnNames;
        //protected Record[] data;
        protected String[][] data;
     
        public MySQLPagingModel(String statement)
        {
            this.statement = statement;
            conn = DBConnection.getConnection();
            row = 0;
            pageOffset = 0;
            pageSize = 100;
            try 
            {
                preparedStatement = conn.prepareStatement("("+statement+") LIMIT ?, ?");
                rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT 0, "+pageSize);
                //rs = DBConnection.executeQuery(statement);
                rsmd = rs.getMetaData();
                //Zeilenzahl berechnen
                Statement stm2 = conn.createStatement();
                ResultSet rs2 = stm2.executeQuery("SELECT COUNT(*) FROM ("+statement+") AS tmp");
                rs2.next();
                rowCount = rs2.getInt(1);
                rs2.close();
                stm2.close();
                //////
                columnCount = rsmd.getColumnCount();
                columnNames = new String[columnCount];
                for (int i=0; i<columnCount; i++)
                {
                    columnNames[i] = rsmd.getColumnName(i+1);
                }
                data = new String[pageSize][columnCount];
                int i=0;
                while (rs.next())
                {
                    for (int j=0; j<columnCount; j++)
                    {
                        data[i][j]= rs.getString(j+1);                  
                    }
                    i++;
                }
                rs.close();
            }
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
     
        //Return values appropriate for the visible table part.
        public int getRowCount() { return Math.min(pageSize, rowCount); }
        public int getColumnCount() { return columnCount; }
     
        // Work only on the visible part of the table.
        public Object getValueAt(int row, int col) 
        {
         //int realRow = row + (pageOffset * pageSize);
         return data[row][col];
        }
        public String getColumnName(int col) 
        {
         return columnNames[col];
        }
        //Use this method to figure out which page you are on.
        public int getPageOffset() { return pageOffset; }
     
        public int getPageCount() 
        { 
         return (int)Math.ceil((double)rowCount / pageSize);
        }
     
        // Use this method if you want to know how big the real table is . . . we
        // could also write "getRealValueAt()" if needed.
        public int getRealRowCount() 
        {
         return rowCount;
        }
     
        public int getPageSize() { return pageSize; }
        /*
        public void setPageSize(int s) 
        { 
         if (s == pageSize) { return; }
         int oldPageSize = pageSize;
         pageSize = s;
         pageOffset = (oldPageSize * pageOffset) / pageSize;
         fireTableDataChanged();
        */
        /*
         if (pageSize < oldPageSize) {
           fireTableRowsDeleted(pageSize, oldPageSize - 1);
         }
         else {
           fireTableRowsInserted(oldPageSize, pageSize - 1);
         }
        */
        //}
     
        //Update the page offset and fire a data changed (all rows).
        public void pageDown() 
        {
         System.out.println(pageOffset);
         if (pageOffset < getPageCount() - 1) 
         {
           pageOffset++;
           try 
           {
               //rs = DBConnection.executeQuery(statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize));
               //preparedStatement = conn.prepareStatement("SELECT * FROM ("+statement+") AS tmp LIMIT ?, ?");
               preparedStatement.setInt(1, (pageOffset*pageSize));
               preparedStatement.setInt(2, pageSize);
               //rs = DBConnection.executeQuery("SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize);
               rs = preparedStatement.executeQuery();
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
               rs.close();
               for (int k=i; k<pageSize; k++)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[k][j] = "";
                   }
               }
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   Update the page offset and fire a data changed (all rows).
        public void pageUp() 
        {
         System.out.println(pageOffset);
         if (pageOffset > 0) 
         {
           pageOffset--;
           try 
           {
               //String test = statement+" LIMIT "+(pageOffset*pageSize)+", "+((pageOffset*pageSize)+pageSize);
               //String test = "SELECT * FROM ("+statement+") AS tmp LIMIT "+(pageOffset*pageSize)+", "+pageSize;
               //rs = DBConnection.executeQuery(test);
               //System.out.println(test);
               preparedStatement.setInt(1, (pageOffset*pageSize));
               preparedStatement.setInt(2, pageSize);
               rs = preparedStatement.executeQuery();
               int i=0;
               while (rs.next() /*&& i<pageSize*/)
               {
                   for (int j=0; j<columnCount; j++)
                   {
                       data[i][j] = rs.getString(j+1);
                   }
                   i++;
               }
               rs.close();
           }
           catch (SQLException e)
           {
               e.printStackTrace();
           }
           fireTableDataChanged();
         }
        }
     
    //   We provide our own version of a scrollpane that includes
    //   the page up and page down buttons by default.
        public static JScrollPane createPagingScrollPaneForTable(JTable jt) 
        {
         JScrollPane jsp = new JScrollPane(jt);
         TableModel tmodel = jt.getModel();
         
         // Don't choke if this is called on a regular table . . .
         if (! (tmodel instanceof MySQLPagingModel || tmodel instanceof PagingModel)) 
         {
           return jsp;
         }
     
         // Okay, go ahead and build the real scrollpane
         final MySQLPagingModel model = (MySQLPagingModel)tmodel;
         final JButton upButton = new JButton(/*new ArrowIcon(ArrowIcon.UP)*/"UP");
         upButton.setEnabled(false);  // starts off at 0, so can't go up
         final JButton downButton = new JButton(/*new ArrowIcon(ArrowIcon.DOWN)*/"DOWN");
         if (model.getPageCount() <= 1) 
         {
           downButton.setEnabled(false);  // One page...can't scroll down
         }
     
         upButton.addActionListener(new ActionListener() 
         {
           public void actionPerformed(ActionEvent ae) 
           {
             model.pageUp();
     
             // If we hit the top of the data, disable the up button.
             if (model.getPageOffset() == 0) 
             {
               upButton.setEnabled(false);
             }
             downButton.setEnabled(true);
           }
         } );
     
         downButton.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent ae) {
             model.pageDown();
     
             // If we hit the bottom of the data, disable the down button.
             if (model.getPageOffset() == (model.getPageCount() - 1)) {
               downButton.setEnabled(false);
             }
             upButton.setEnabled(true);
           }
         } );
     
         // Turn on the scrollbars; otherwise we won't get our corners.
         jsp.setVerticalScrollBarPolicy
             (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         jsp.setHorizontalScrollBarPolicy
             (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
     
         // Add in the corners (page up/down).
         jsp.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER, upButton);
         jsp.setCorner(ScrollPaneConstants.LOWER_RIGHT_CORNER, downButton);
     
         return jsp;
        }
    }
     

  10. #40
    Avatar von tekilla209
    tekilla209 tekilla209 ist offline Mitglied Silber
    Registriert seit
    Apr 2007
    Beiträge
    60
    Eine Frage hätt ich da noch.
    Wo hastn Du das ArrowIcon her?
    new ArrowIcon(ArrowIcon.UP) kennt eclipse bei mir nicht

    hab was gefunden:
    org.gui4j.core.swing.calendar;

    meintest Du das?
    Geändert von tekilla209 (17.09.07 um 12:50 Uhr)
     

  11. #41
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Ja, es gibt aber wohl noch mehr Varianten im Netz..

    Schöne Lösung! Hast gut gekämpft....

    Grüße
     
    I didn't write this; a very complex macro did.

  12. #42
    Milkabär Milkabär ist offline Grünschnabel
    Registriert seit
    Feb 2010
    Beiträge
    3
    Ich habe gute Erfahrungen mit gc() gemacht. Nachdem ich mehrere Connection-Objekte angelegt hatte ist mir der Speicher übergelaufen, und ich war zu dämlich, die Sache mit close()-Statements in den Griff zu bekommen. Ich habe den Fehler dann durch ein try-catch lokalisiert, und im catch-Block den Garbage-Collector aufgerufen. Vom Programmierstil sicherlich quick&dirty, aber es funktioniert!
     

  13. #43
    kritzel3000 kritzel3000 ist offline Rookie
    Registriert seit
    Feb 2012
    Beiträge
    1
    Hallo
    ich hab eine frage:
    Muß ich unbedingt den Zeiger auf null setzen, damit der GC das löscht?

    Beispiel:
    ich gebe
    Code :
    1
    2
    3
    
    JLabel label = new JLabel();
    //label = null;
    label = new JLabel();
    ein.
    wird das alte Objekt dann trotzdem vom GC gelöscht?
     

  14. #44
    limago limago ist offline Mitglied Brokat
    Registriert seit
    May 2007
    Ort
    Riedstadt (Hessen)
    Beiträge
    354
    Hallo

    Objekte werden gelöscht, wenn sie nicht mehr erreichbar sind. Du musst den Zeiger nicht auf "null" setzen. Wenn keine zweite Referenz auf das JLabel verweist, wird es weggeräumt.
     
    I didn't write this; a very complex macro did.

  15. #45
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.503
    Also ja, dein Code ist so in Ordnung.

    Falls du die Frage deswegen stellst, weil es nicht gelöscht wird:
    Es muss nicht sofort passieren.
    Der GC kann das machen, wann er will.

    PS: Willkommen bei tutorials.de
     
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

Ähnliche Themen

  1. Warenwirtschafts-System vs. ERP-System
    Von hikeda_ya im Forum Coders Talk
    Antworten: 2
    Letzter Beitrag: 15.09.10, 11:03
  2. system()
    Von Anfänger007 im Forum C/C++
    Antworten: 0
    Letzter Beitrag: 24.10.07, 12:21
  3. 2.1-System
    Von tittli im Forum Audiotechnik, Recording & Audio-Software
    Antworten: 3
    Letzter Beitrag: 27.09.07, 19:01
  4. System::Byte => System::String
    Von dertobian im Forum C/C++
    Antworten: 6
    Letzter Beitrag: 25.08.07, 18:57
  5. Was für ein System
    Von MediaPlanet im Forum PHP
    Antworten: 3
    Letzter Beitrag: 25.08.03, 00:03