Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Databases / November 2007

Tip: Looking for answers? Try searching our database.

Connection and PreparedStatement

Thread view: 
francan00@yahoo.com - 14 Nov 2007 00:38 GMT
Is this a good way to insert and update into an Oracle database or is
there anything I can improve?

public class Sports
{
   private Connection connection;

       public Sports() {
          connection = new DatabaseConnection().getConnection();
       }

       public void Inserter(BeanMain objref) throws SQLException
       {
         if(connection != null)
         {
           PreparedStatement stat =
connection.prepareStatement("Insert into FranchiseTable (team,
manager) values (?,?)");
           stat.setString(1, objref.getTeam());
           stat.setString(2, objref.getManager());
           stat.executeUpdate();
           stat.close();
         }
       }

    public void Updater(BeanMain objref) throw SQLException
    {
      if(connection != null)
       {
         PreparedStatement stat = connection.prepareStatement("update
PlayersTable set Id = ? where name LIKE ? ");
          stat.setInt(1, objref.getId());
          stat.setString(2, objref.getName());
          stat.executeUpdate():
          stat.close();
       }
    }

  public void DatabasesUpdIns(BeanMain objref)
  {
       try
      {
                 Inserter(objref);
                 Updaterer(objref);
      }
      catch(SQLException ex)
      {
             System.out.println(ex);
      }
      finally
      {
            connection.close();
      }

}
Lew - 14 Nov 2007 01:34 GMT
> Is this a good way to insert and update into an Oracle database or is
> there anything I can improve?
[quoted text clipped - 5 lines]
>         public Sports() {
>            connection = new DatabaseConnection().getConnection();

How about throwing an exception if this fails?

>         }

You set the connection in the constructor, but close() of it before the object
is disposed.  You never set the connection to null after it closes.  You will
have bugs.

I recommend against creating the connection in the constructor, but if you do
you must make sure that it is closed *at the end of the object's life*, or at
least its useful life, and that it cannot be re-used after close().  A wrapper
method like dispose() around the close() is good, except for imposing a
responsibility on the client to use it.

If you open and close the connection in each service method you have better
control and the client need not concern itself with connection matters.  You
also don't tie the connection life to the object's life; if the object lingers
past its useful time you don't waste the connection.

>         public void Inserter(BeanMain objref) throws SQLException
>         {
>           if(connection != null)

This condition will never be true, the way you wrote the class.  That means
this method could be called with a close()d, non-null connection.

>           {
>             PreparedStatement stat =
[quoted text clipped - 10 lines]
>      {
>        if(connection != null)

/ibid./

>         {
>           PreparedStatement stat = connection.prepareStatement("update
[quoted text clipped - 23 lines]
>
> }

Good start, but a breeding ground for bugs in its current form.

Signature

Lew

David Harper - 14 Nov 2007 06:39 GMT
[SNIP]
> If you open and close the connection in each service method you have
> better control and the client need not concern itself with connection
> matters.  You also don't tie the connection life to the object's life;
> if the object lingers past its useful time you don't waste the connection.

On the other hand, it's generally regarded as poor practice to
repeatedly execute {open connection, do something with it, close
connection}.  Opening a connection to some RDBMSs is a slow and
expensive operation, and performance will suffer, both at the client end
and the server end.

David Harper
Cambridge, England
Lew - 14 Nov 2007 07:16 GMT
> [SNIP]
>> If you open and close the connection in each service method you have
[quoted text clipped - 8 lines]
> expensive operation, and performance will suffer, both at the client end
> and the server end.

Usual solution to that is a connection pool.  Abstract the connection
responsibility one layer away from the application logic and it simplifies the
engineering.

Which is worse, to take a while to construct a connection, or to run out of
connections because your objects never let them go?

Signature

Lew

David Harper - 14 Nov 2007 07:25 GMT
>> [SNIP]
>>> If you open and close the connection in each service method you have
[quoted text clipped - 15 lines]
> Which is worse, to take a while to construct a connection, or to run out
> of connections because your objects never let them go?

Better *not* to let each object create its own connection.  That way,
madness lies.  As you say, this argues strongly for a connection pool.

David Harper
Cambridge, England
Lew - 14 Nov 2007 07:41 GMT
Lew wrote:
>> Which is worse, to take a while to construct a connection, or to run
>> out of connections because your objects never let them go?

> Better *not* to let each object create its own connection.  That way,
> madness lies.  As you say, this argues strongly for a connection pool.

The application code doesn't change when you switch to a connection pool.  The
semantics of the close() call change to "release to the pool" instead of
"destroy".

Signature

Lew

Ruud de Koter - 14 Nov 2007 11:17 GMT
Hi Francan00,

Please find some comments in the code.

> public class Sports
> {
[quoted text clipped - 3 lines]
>            connection = new DatabaseConnection().getConnection();
>         }

As mentioned before, this doesn't seem to be the ideal place to open a
connection. Also, there is no exception handling, and exception handling
in this place is always a tricky thing, in my experience.

>         public void Inserter(BeanMain objref) throws SQLException

BeanMain sounds very generic. Is there any check this is indeed an
instance of the class you want to be handling (apparently a class that
has a team and a manager member)?

>         {
>           if(connection != null)

What happens if (for whatever reason) connection is null? Nothing? Is
that desired behaviour?

>           {
>             PreparedStatement stat =
[quoted text clipped - 8 lines]
>
>      public void Updater(BeanMain objref) throw SQLException

Typo: 'throw' should be 'throws'

>      {
>        if(connection != null)
>         {
>           PreparedStatement stat = connection.prepareStatement("update
> PlayersTable set Id = ? where name LIKE ? ");

Why do you use LIKE here? I wouldn't expect a name to contain any
wildcard characters. If there are no wildcards the LIKE operator will
have the same functionality as equality. It only serves to create confusion.

>            stat.setInt(1, objref.getId());
>            stat.setString(2, objref.getName());
[quoted text clipped - 17 lines]
>        {
>              connection.close();

What happens if the connection doesn't close?

>        }
>
> }

Not homework, by any chance?

Regards,

Ruud de Koter.
francan00@yahoo.com - 14 Nov 2007 23:15 GMT
Thanks for all the messages.

I modified it so the connection is established in each method which I
assume is the more efficient way??
Please advise if this is okay?

public class Sports
{
       public void inserter(SportsBean objref) throws SQLException
       {
         Connection connection = new
DatabaseConnection().getConnection();
           PreparedStatement stat =
connection.prepareStatement("Insert into FranchiseTable (team,
manager) values (?,?)");
           stat.setString(1, objref.getTeam());
           stat.setString(2, objref.getManager());
           stat.executeUpdate();
           stat.close();
           connection.close();
         }
       }

    public void updater(SportsBean objref) throw SQLException
    {
         Connection connection = new
DatabaseConnection().getConnection();
         PreparedStatement stat =
connection.prepareStatement("update
PlayersTable set Id = ? where name LIKE ? ");
          stat.setInt(1, objref.getId());
          stat.setString(2, objref.getName());
          stat.executeUpdate():
          stat.close();
          connection.close();
       }
    }

  public void databasesUpdIns(SportsBean objref)
  {
       Connection connection = null;
       try
      {
                 connection = new
DatabaseConnection().getConnection();
                 inserter(objref);
                 updaterer(objref);
      }
      catch(SQLException ex)
      {
             System.out.println(ex);
      }
      finally
      {
            connection.close();
      }
Lew - 15 Nov 2007 01:18 GMT
> I modified it so the connection is established in each method which I
> assume is the more efficient way??

There's efficiency, and there's safety.

> Please advise if this is okay?

Basically good.  Written this way, you push the question of pooling an so
forth into the driver.

The safety aspect is to check for return values and exceptions.  If you get a
null connection back, or an exception, from its construction, you will have
trouble.  If you get an exception later, you risk not closing the connection,
hastening the saturation of your connection limit.

By relaying the SQLException you're adding to the burden of Sports client
classes to deal with the exception at that low level.  You should either eat
the Exception, turning it into a return code, or rethrow as an
ApplicationException (your custom derivative).

'objref' is not a very useful name for a variable.

Here's an example of safety-first connection use, leaving pooling to the
driver, much like yours except for the extra checks and the use of
DriverManager instead of the custom class:

 package foo.sports;
 import org.apache.log4j.Logger;
 public class Sportster
 {
  private static final String LOCATION =
    "jdbc:postgresql://localhost:5432/sportster";
  private static final String USER = "sportster";
  private static final String PWD  = "sportster";

  private static final String INSERT =
    "INSERT INTO franchise ( team, manager ) VALUES (?, ?)";

  private static final String UPDATE =
    "UPDATE franchise SET manager = ? WHERE team ?";

  private final Logger logger = Logger.getLogger( getClass() );

  public void insert( Sports entity )
      throws AppException
  {
    Connection connection;
    try
    {
      connection = DriverManager.getConnection( LOCATION, USER, PWD );
    }
    catch ( SQLException ex )
    {
      logger.error( "Connection failure: "+ ex.getMessage(), ex );
      throw new AppException( ex );
    }

    PreparedStatement stat = null;
    try
    {
      connection.setAutoCommit( false );

      stat = connection.prepareStatement( INSERT );
      stat.setString( 1, entity.getTeam() );
      stat.setString( 2, entity.getManager() );

      int rows = stat.executeUpdate();
      connection.commit();
      logger.debug( "Inserted "+ rows +" rows." );
    }
    catch ( SQLException ex )
    {
      logger.error( "Insert failure: "+ ex.getMessage(), ex );
      try
      {
        connection.rollback();
      }
      catch ( SQLException exc )
      {
        logger.error( "Rollback failure: "+ ex.getMessage(), exc );
        throw new AppException( ex );
      }
      throw new AppException( ex );
    }
    finally
    {
      if ( stat != null )
      {
        stat.close();
      }
      try
      {
        connection.close();
      }
      catch ( SQLException exc )
      {
        logger.error( "Close failure: "+ ex.getMessage(), exc );
        throw new AppException( ex );
      }
    }
  }  // insert()

// similarly for update(), delete(), query(), find(), etc.
 }   // Sportster

This example might cry out to you for refactoring.

Signature

Lew

francan00@yahoo.com - 15 Nov 2007 02:27 GMT
> This example might cry out to you for refactoring.
>
> --
> Lew

Your example is excellent and I appreciate all your time you gave my
question to guide me in the right direction.

Many thanks!!!
Ruud de Koter - 15 Nov 2007 20:30 GMT
> Thanks for all the messages.
>
> I modified it so the connection is established in each method which I
> assume is the more efficient way??
> Please advise if this is okay?

Hi Francan00,

Your code doesn't generate the same enthousiasm with me as it does with
Lew. Two points I don't think Lew brought up:

- how many times do you open a connection when databasesUpdIns() is
executed? How many of these connections are actually used?
- in my view the use of the 'LIKE' operator is still a serious problem:
you are sending a statement to the database that is *not* what you want
it to be (or you don't know how to ask what you want to ask). How is
your database going to return a proper and timely answer when the
request is incorrect? This may seem quite harsh, but do you know what
each and every optimizer will do with the 'LIKE' operator?

Regards,

Ruud de Koter.

> public class Sports
> {
[quoted text clipped - 46 lines]
>              connection.close();
>        }


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.