0

I have a project that needs to connect to a database. I'm reading the database connection info in from a config.xml file, however, I'm stuck on the part where I define the DataSource for a particular db engine (technically, it's the dbms, but the terms seem to be used interchangeably). Here's the relevant code snippet:

String engine = get(xmldoc, "engine");
if (engine == "postgres")
{
    PGSimpleDataSource ds = new PGSimpleDataSource();
}
else if (engine == "mssql")
{
    SQLServerDataSource ds = new SQLServerDataSource();
}
else if (engine == "sqlite")
{
    SQLiteDataSource ds = new SQLiteDataSource();
}
else
{
    throw new Exception(String.format("Unknown DBMS type %s", engine));
}

ds.setServerName(get(xmldoc, "hostname"));
ds.setDatabaseName(get(xmldoc, "databasename"));
ds.setUser(get(xmldoc, "username"));

When I try to compile it, I get a bunch of error: cannot find symbol for every reference to ds. After a little digging, I found that this is because my ds variable is local to the if-statement in which it's declared (ref: Cannot find symbol if statement error). Unlike in that question though, I can't simply declare it at the beginning because I don't know what particular DataSource it's going to be.

So, what is the best approach to dynamically set my DataSource? Preferably without putting all my initialization code inside each if-statement because then I'd have to put all my db calls there as well. Is there some way to initially declare ds to be a generic DataSource and then cast it to a particular one in the if-statements?

asdf
  • 109
  • 7

1 Answers1

0

First of all, you are comparing strings the wrong way:

But the solution to your real problem is to use polymorphism.

  1. You need to define a DataSource interface that declares all of the methods that your application is going to call.

  2. All of your existing database specific data source classes need to implement the DataSource interface and its methods. (Maybe you could use an abstract class to implement some of the common functionality.)

  3. Declare ds as a DataSource; e.g.

    String engine = get(xmldoc, "engine");
    DataSource ds = null;
    if (engine.equals("postgres")) {
        ds = new PGSimpleDataSource();
    }
    else if (engine.equals("mssql")) {
        ds = new SQLServerDataSource();
    }
    else if (engine.equals("sqlite")) {
        ds = new SQLiteDataSource();
    }
    else {
        throw new Exception(String.format("Unknown DBMS type %s", engine));
    }
    
    ds.setServerName(get(xmldoc, "hostname"));
    ds.setDatabaseName(get(xmldoc, "databasename"));
    ds.setUser(get(xmldoc, "username"));
    

The problem with the above is that the standard DataSource interface and classes don't implement the methods that you want to use. Therefore you are going to have to create your own interface and wrapper classes for PGSimpleDataSource, SQLServerDataSource and so no.

(Are you sure you want to write this code yourself? Wouldn't it be better to find and use an existing library? Or if it is only setting the server name, database and user, do the "connection" configuration within the if / else branches using source specific API methods.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216