Avatar billede gvp Nybegynder
05. februar 2010 - 14:45 Der er 3 kommentarer og
1 løsning

java + oracle + merge + bind = fejl

Hej,
jeg ønsker bruge merge til at indsætte data i en oracle database ved hjælp af prepared statements for at undgå for mange hardparses og laches, men jeg kan ikke få det til at virke.

jeg kan sagtens få det hele til at virke i PHP, problemet er at få det til at virke i java.

jeg paster lige hele min metode til at skrive til database (jeg er HELT ny til java, så bær over med mig):

public void writeData() throws SQLException{
        String sql = "MERGE INTO masterproduct dest " +
            "USING (SELECT ? as chainid, ? as sku, ? as name, ? as price, ? as description, ? as url, ? as picture, ? as stock, ? as internetprice FROM DUAL) src " +
            "ON (src.sku = dest.sku AND src.chainid = dest.chainid) " +
            "WHEN MATCHED THEN " +
                "UPDATE SET " +
                "dest.price = src.price," +
                "dest.description = src.description," +
                "dest.url = src.url," +
                "dest.picture = src.picture," +
                "dest.stock = src.stock," +
                "dest.internetprice = src.internetprice," +
                "dest.lastinstock = (SELECT CASE WHEN 1 = (src.stock) THEN SYSDATE END lastinstock FROM DUAL)," +
                "dest.latestextractiondate = SYSDATE," +
                "dest.extractedinlatestrun = 1 " +
            "WHEN NOT MATCHED THEN " +
                "INSERT (" +
                    "dest.chainid," +
                    "dest.sku," +
                    "dest.name," +
                    "dest.price," +
                    "dest.description," +
                    "dest.url," +
                    "dest.picture," +
                    "dest.stock," +
                    "dest.lastinstock," +
                    "dest.internetprice" +
                ") " +
                "VALUES (" +
                    "src.chainid," +
                    "src.sku," +
                    "src.name," +
                    "src.price," +
                    "src.description," +
                    "src.url," +
                    "src.picture" +
                    "src.stock," +
                    "(SELECT CASE WHEN 1 = (src.stock) THEN SYSDATE ELSE null END lastinstock FROM DUAL)," +
                    "src.internetprice" +
                ")";
        PreparedStatement stmt = this.conn.prepareStatement(sql);
        try{
            this.conn.setAutoCommit(false);
            for (int i =0; i< this.size(); i++){
                MasterProduct mp = this.get(i);
                stmt.setInt(1, mp.getChainid());
                stmt.setString(2, mp.getId());
                stmt.setString(3, mp.getName());
                stmt.setDouble(4, mp.getPrice());
                stmt.setCharacterStream(5, new StringReader(mp.getDesc()),mp.getDesc().length());
                stmt.setString(6, mp.getUrl());
                stmt.setString(7, mp.getPicture());
                stmt.setInt(8, mp.isStock() ? 1 : 0);
                stmt.setInt(9, mp.isInternetprice() ? 1 : 0);
                stmt.addBatch();
            }
            stmt.executeBatch();
            this.conn.commit();
            this.clear();
        }
        catch (SQLException e){e.printStackTrace();}
        finally{stmt.close();}
    }

fejlen jeg får ved dette er som flg:
java.sql.BatchUpdateException: ORA-00947: not enough values


når jeg så forsøger at at køre en lille test får jeg så en anden fejl som jeg håber/tror også er det der udløser fejlen i mit metode længere oppe.
conn.setAutoCommit(false);       
        String query = "SELECT ? title, ? author, ? body FROM dual";
        PreparedStatement stmt = conn.prepareStatement(query);
       
        stmt.setString(1, "bibo");
        stmt.setString(2, "lala");
        stmt.setString(3, "lulu");
        ResultSet rset = stmt.executeQuery(query);
        System.out.println (rset.getRow());
       
       
        while (rset.next()) {
            System.out.println (rset.getString(1));
     
        }
        stmt.close();

her får jeg en anden fejl:
Exception in thread "main" java.sql.SQLException: ORA-03115: unsupported network datatype or representation


det får mig frem til at egentlige spørgsmål her på experten:
Hvordan binder man variabler når man bare vil lave en select fra DUAL? Jeg skal jo have mine variabler ind i nogle felter på en eller anden måde...
For lige at gøre det klart for alle, jeg SKAL bruge et prepared statement, ellers går performance på serveren lige lukt til h***vede - så det duer IKKE at paste dem ind i sql strengen.
Det må kunne lade sig gøre i java...
Avatar billede gvp Nybegynder
05. februar 2010 - 15:21 #1
ok, det manglede et komma, så nu får jeg ikke længere "not enough values".

nu hænger den bare...(!!!) :-(
Avatar billede gvp Nybegynder
05. februar 2010 - 15:32 #2
det lader til at være stmt.executeBatch(); der får det hele til at hænge. Der sker intet. heller ikke selvom jeg undlader at indsætte clob & double...
Avatar billede gvp Nybegynder
05. februar 2010 - 16:04 #3
Ok...det virker nu. Jeg skulle reboote min PC! Der må have været noget i vejen med min Eclipse IDE eller noget. Nu hænger den i hvert fald ikke længere.

dette var løsningen til sidst:

public void writeData() throws SQLException{
        String sql = "MERGE INTO masterproduct dest " +
            "USING (SELECT ? chainid, ? sku, ? name, ? price, ? description, ? url, ? picture, ? stock, ? internetprice FROM DUAL) src " +
            "ON (src.sku = dest.sku AND src.chainid = dest.chainid) " +
            "WHEN MATCHED THEN " +
                "UPDATE SET " +
                "dest.price = src.price," +
                "dest.description = src.description," +
                "dest.url = src.url," +
                "dest.picture = src.picture," +
                "dest.stock = src.stock," +
                "dest.internetprice = src.internetprice," +
                "dest.lastinstock = (SELECT CASE WHEN 1 = (src.stock) THEN SYSDATE END lastinstock FROM DUAL)," +
                "dest.latestextractiondate = SYSDATE," +
                "dest.extractedinlatestrun = 1 " +
            "WHEN NOT MATCHED THEN " +
                "INSERT (" +
                    "dest.chainid," +
                    "dest.sku," +
                    "dest.name," +
                    "dest.price," +
                    "dest.description," +
                    "dest.url," +
                    "dest.picture," +
                    "dest.stock," +
                    "dest.lastinstock," +
                    "dest.internetprice" +
                ") " +
                "VALUES (" +
                    "src.chainid," +
                    "src.sku," +
                    "src.name," +
                    "src.price," +
                    "src.description," +
                    "src.url," +
                    "src.picture," +
                    "src.stock," +
                    "(SELECT CASE WHEN 1 = (src.stock) THEN SYSDATE ELSE null END lastinstock FROM DUAL)," +
                    "src.internetprice" +
                ")";
        PreparedStatement stmt = this.conn.prepareStatement(sql);
        try{
            this.conn.setAutoCommit(false);
            for (int i =0; i< this.size(); i++){
                System.out.println(i);
                MasterProduct mp = this.get(i);
                stmt.setInt(1, mp.getChainid());
                stmt.setString(2, mp.getId());
                stmt.setString(3, mp.getName());
                stmt.setDouble(4, mp.getPrice());
                stmt.setCharacterStream(5, new StringReader(mp.getDesc()),mp.getDesc().length());
                stmt.setString(6, mp.getUrl());
                stmt.setString(7, mp.getPicture());
                stmt.setInt(8, mp.isStock() ? 1 : 0);
                stmt.setInt(9, mp.isInternetprice() ? 1 : 0);
                stmt.addBatch();
            }
            stmt.executeBatch();
            stmt.clearBatch();
            this.conn.commit();
            this.clear();
        }
        catch (SQLException e){e.printStackTrace();}
        finally{stmt.close();}
    }
Avatar billede gvp Nybegynder
05. februar 2010 - 16:04 #4
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester