Implementation of DDLUTILS-197

git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@649998 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/org/apache/ddlutils/Platform.java b/src/java/org/apache/ddlutils/Platform.java
index c0b70d2..79dc610 100644
--- a/src/java/org/apache/ddlutils/Platform.java
+++ b/src/java/org/apache/ddlutils/Platform.java
@@ -949,6 +949,27 @@
     public List fetch(Database model, String sql, Collection parameters, Table[] queryHints, int start, int end) throws DatabaseOperationException;

 

     /**

+     * Determines whether the given dyna bean is stored in the database. Note that this checks only

+     * checks the primary key, not the other attributes.

+     * 

+     * @param model    The database model to use

+     * @param dynaBean The bean

+     * @return <code>true</code> if a bean with this primary key exists in the database

+     */

+    public boolean exists(Database model, DynaBean dynaBean);

+

+    /**

+     * Determines whether the given dyna bean is stored in the database. Note that this checks only

+     * checks the primary key, not the other attributes.

+     * 

+     * @param connection The connection

+     * @param model      The database model to use

+     * @param dynaBean   The bean

+     * @return <code>true</code> if a bean with this primary key exists in the database

+     */

+    public boolean exists(Connection connection, Database model, DynaBean dynaBean);

+

+    /**

      * Stores the given bean in the database, inserting it if there is no primary key

      * otherwise the bean is updated in the database.

      * 

@@ -958,6 +979,16 @@
     public void store(Database model, DynaBean dynaBean) throws DatabaseOperationException;

 

     /**

+     * Stores the given bean in the database, inserting it if there is no primary key

+     * otherwise the bean is updated in the database.

+     * 

+     * @param connection The connection

+     * @param model      The database model to use

+     * @param dynaBean   The bean to store

+     */

+    public void store(Connection connection, Database model, DynaBean dynaBean) throws DatabaseOperationException;

+

+    /**

      * Returns the sql for inserting the given bean.

      * 

      * @param model    The database model to use

diff --git a/src/java/org/apache/ddlutils/platform/PlatformImplBase.java b/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
index 1edc13e..13663a6 100644
--- a/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
+++ b/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
@@ -24,6 +24,7 @@
 import java.lang.reflect.InvocationTargetException;

 import java.lang.reflect.Method;

 import java.math.BigDecimal;

+import java.sql.BatchUpdateException;

 import java.sql.Blob;

 import java.sql.Clob;

 import java.sql.Connection;

@@ -2160,7 +2161,16 @@
             }

             catch (SQLException ex)

             {

-                throw new DatabaseOperationException("Error while inserting into the database", ex);

+                if (ex instanceof BatchUpdateException)

+                {

+                    SQLException sqlEx = ((BatchUpdateException)ex).getNextException();

+

+                    throw new DatabaseOperationException("Error while inserting into the database", sqlEx);

+                }

+                else

+                {

+                    throw new DatabaseOperationException("Error while inserting into the database", ex);

+                }

             }

         }

     }

@@ -2477,16 +2487,77 @@
     }

 

     /**

-     * Determines whether the given dyna bean is stored in the database.

-     * 

-     * @param dynaBean   The bean

-     * @param connection The connection

-     * @return <code>true</code> if this dyna bean has a primary key

+     * {@inheritDoc}

      */

-    protected boolean exists(Connection connection, DynaBean dynaBean)

+    public boolean exists(Database model, DynaBean dynaBean)

     {

-        // TODO: check for the pk value, and if present, query against database

-        return false;

+        Connection connection = borrowConnection();

+

+        try

+        {

+            return exists(connection, model, dynaBean);

+        }

+        finally

+        {

+            returnConnection(connection);

+        }

+    }

+

+

+    /**

+     * {@inheritDoc}

+     */

+    public boolean exists(Connection connection, Database model, DynaBean dynaBean)

+    {

+        SqlDynaClass      dynaClass   = model.getDynaClassFor(dynaBean);

+        SqlDynaProperty[] primaryKeys = dynaClass.getPrimaryKeyProperties();

+        

+        if (primaryKeys.length == 0)

+        {

+            return false;

+        }

+

+        PreparedStatement stmt = null;

+

+        try

+        {

+            StringBuffer sql = new StringBuffer();

+

+            sql.append("SELECT * FROM ");

+            sql.append(_builder.getDelimitedIdentifier(dynaClass.getTable().getName()));

+            sql.append(" WHERE ");

+

+            for (int idx = 0; idx < primaryKeys.length; idx++)

+            {

+                String key = primaryKeys[idx].getColumn().getName();

+

+                if (idx > 0)

+                {

+                    sql.append(" AND ");

+                }

+                sql.append(_builder.getDelimitedIdentifier(key));

+                sql.append("=?");

+            }

+

+            stmt = connection.prepareStatement(sql.toString());

+

+            for (int idx = 0; idx < primaryKeys.length; idx++)

+            {

+                setObject(stmt, idx + 1, dynaBean, primaryKeys[idx]);

+            }

+

+            ResultSet resultSet = stmt.executeQuery();

+

+            return resultSet.next();

+        }

+        catch (SQLException ex)

+        {

+            throw new DatabaseOperationException("Error while reading from the database", ex);

+        }

+        finally

+        {

+            closeStatement(stmt);

+        }

     }

 

     /**

@@ -2498,14 +2569,7 @@
 

         try

         {

-            if (exists(connection, dynaBean))

-            {

-                update(connection, model, dynaBean);

-            }

-            else

-            {

-                insert(connection, model, dynaBean);

-            }

+            store(connection, model, dynaBean);

         }

         finally

         {

@@ -2514,6 +2578,21 @@
     }

 

     /**

+     * {@inheritDoc}

+     */

+    public void store(Connection connection, Database model, DynaBean dynaBean) throws DatabaseOperationException

+    {

+        if (exists(connection, model, dynaBean))

+        {

+            update(connection, model, dynaBean);

+        }

+        else

+        {

+            insert(connection, model, dynaBean);

+        }

+    }

+

+    /**

      * Creates the SQL for deleting an object of the given type. If a concrete bean is given,

      * then a concrete delete statement is created, otherwise a delete statement usable in a

      * prepared statement is build.

diff --git a/src/test/org/apache/ddlutils/dynabean/TestDynaSqlQueries.java b/src/test/org/apache/ddlutils/dynabean/TestDynaSqlQueries.java
index 5c2e90b..23bf810 100644
--- a/src/test/org/apache/ddlutils/dynabean/TestDynaSqlQueries.java
+++ b/src/test/org/apache/ddlutils/dynabean/TestDynaSqlQueries.java
@@ -19,6 +19,7 @@
  * under the License.

  */

 

+import java.util.ArrayList;

 import java.util.List;

 

 import org.apache.commons.beanutils.DynaBean;

@@ -311,4 +312,266 @@
         assertFalse(it.hasNext());

         assertFalse(it.isConnectionOpen());

     }

+

+    /**

+     * Tests the insert method.

+     */

+    public void testInsertSingle() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean  = new SqlDynaBean(dynaClass);

+

+        dynaBean.set("TheId", new Integer(1));

+        dynaBean.set("TheText", "Text 1"); 

+

+        getPlatform().insert(getModel(), dynaBean);

+

+        List beans = getPlatform().fetch(getModel(),

+                                         "SELECT * FROM TestTable",

+                                         new Table[] { getModel().getTable(0) });

+

+        assertEquals(1,

+                     beans.size());

+

+        DynaBean bean = (DynaBean)beans.get(0);

+

+        assertEquals(new Integer(1),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 1",

+                     getPropertyValue(bean, "TheText"));

+    }

+

+    /**

+     * Tests the insert method.

+     */

+    public void testInsertMultiple() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean1 = new SqlDynaBean(dynaClass);

+        DynaBean     dynaBean2 = new SqlDynaBean(dynaClass);

+        DynaBean     dynaBean3 = new SqlDynaBean(dynaClass);

+

+        dynaBean1.set("TheId", new Integer(1));

+        dynaBean1.set("TheText", "Text 1");

+        dynaBean2.set("TheId", new Integer(2));

+        dynaBean2.set("TheText", "Text 2");

+        dynaBean3.set("TheId", new Integer(3));

+        dynaBean3.set("TheText", "Text 3");

+

+        List dynaBeans = new ArrayList();

+

+        dynaBeans.add(dynaBean1);

+        dynaBeans.add(dynaBean2);

+        dynaBeans.add(dynaBean3);

+

+        getPlatform().insert(getModel(), dynaBeans);

+

+        List beans = getPlatform().fetch(getModel(),

+                                         "SELECT * FROM TestTable",

+                                         new Table[] { getModel().getTable(0) });

+

+        assertEquals(3,

+                     beans.size());

+

+        DynaBean bean = (DynaBean)beans.get(0);

+

+        assertEquals(new Integer(1),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 1",

+                     getPropertyValue(bean, "TheText"));

+        

+        bean = (DynaBean)beans.get(1);

+

+        assertEquals(new Integer(2),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 2",

+                     getPropertyValue(bean, "TheText"));

+

+        bean = (DynaBean)beans.get(2);

+

+        assertEquals(new Integer(3),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 3",

+                     getPropertyValue(bean, "TheText"));

+    }

+

+    /**

+     * Tests the update method.

+     */

+    public void testUpdate() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        insertData(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<data>\n"+

+            "  <TestTable TheId='1' TheText='Text 1'/>\n"+

+            "</data>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean  = new SqlDynaBean(dynaClass);

+

+        dynaBean.set("TheId", new Integer(1));

+        dynaBean.set("TheText", "Text 10"); 

+

+        getPlatform().update(getModel(), dynaBean);

+

+        List beans = getPlatform().fetch(getModel(),

+                                         "SELECT * FROM TestTable",

+                                         new Table[] { getModel().getTable(0) });

+

+        assertEquals(1,

+                     beans.size());

+

+        DynaBean bean = (DynaBean)beans.get(0);

+

+        assertEquals(new Integer(1),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 10",

+                     getPropertyValue(bean, "TheText"));

+    }

+

+    /**

+     * Tests the exists method.

+     */

+    public void testExists() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        insertData(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<data>\n"+

+            "  <TestTable TheId='1' TheText='Text 1'/>\n"+

+            "  <TestTable TheId='3' TheText='Text 3'/>\n"+

+            "</data>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean1 = new SqlDynaBean(dynaClass);

+        DynaBean     dynaBean2 = new SqlDynaBean(dynaClass);

+        DynaBean     dynaBean3 = new SqlDynaBean(dynaClass);

+

+        dynaBean1.set("TheId", new Integer(1));

+        dynaBean1.set("TheText", "Text 1"); 

+        dynaBean2.set("TheId", new Integer(2));

+        dynaBean2.set("TheText", "Text 2"); 

+        dynaBean3.set("TheId", new Integer(3));

+        dynaBean3.set("TheText", "Text 30"); 

+

+        assertTrue(getPlatform().exists(getModel(), dynaBean1));

+        assertFalse(getPlatform().exists(getModel(), dynaBean2));

+        assertTrue(getPlatform().exists(getModel(), dynaBean3));

+    }

+

+

+    /**

+     * Tests the store method.

+     */

+    public void testStoreNew() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean  = new SqlDynaBean(dynaClass);

+

+        dynaBean.set("TheId", new Integer(1));

+        dynaBean.set("TheText", "Text 1"); 

+

+        getPlatform().store(getModel(), dynaBean);

+

+        List beans = getPlatform().fetch(getModel(),

+                                         "SELECT * FROM TestTable",

+                                         new Table[] { getModel().getTable(0) });

+

+        assertEquals(1,

+                     beans.size());

+

+        DynaBean bean = (DynaBean)beans.get(0);

+

+        assertEquals(new Integer(1),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 1",

+                     getPropertyValue(bean, "TheText"));

+    }

+

+    /**

+     * Tests the store method.

+     */

+    public void testStoreExisting() throws Exception

+    {

+        createDatabase(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database name='ddlutils'>\n"+

+            "  <table name='TestTable'>\n"+

+            "    <column name='TheId' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='TheText' type='VARCHAR' size='15'/>\n"+

+            "  </table>\n"+

+            "</database>");

+

+        insertData(

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<data>\n"+

+            "  <TestTable TheId='1' TheText='Text 1'/>\n"+

+            "</data>");

+

+        SqlDynaClass dynaClass = SqlDynaClass.newInstance(getModel().getTable(0));

+        DynaBean     dynaBean  = new SqlDynaBean(dynaClass);

+

+        dynaBean.set("TheId", new Integer(1));

+        dynaBean.set("TheText", "Text 10"); 

+

+        getPlatform().store(getModel(), dynaBean);

+

+        List beans = getPlatform().fetch(getModel(),

+                                         "SELECT * FROM TestTable",

+                                         new Table[] { getModel().getTable(0) });

+

+        assertEquals(1,

+                     beans.size());

+

+        DynaBean bean = (DynaBean)beans.get(0);

+

+        assertEquals(new Integer(1),

+                     getPropertyValue(bean, "TheId"));

+        assertEquals("Text 10",

+                     getPropertyValue(bean, "TheText"));

+    }

 }