Since Connection and Statements are interfaces, interface methods will be abstract by default. How can we create Connection and Statement interfaces in our Java program while connecting to the database?
Actually the implementation is provided by JDBC drivers. And the API give you a way to use the thing. Look at this example.
The implementations are provided by the JDBC driver for your database. e.g. for MySql you download the JDBC Driver for MySQL (Connector/J) and place the jar file on the classpath for your application.
Then you make a call to DriverManager (e.g.) this gives you a instance of a class which implements the Connection interface.
Connection c = DriverManager.getConnection("jdbc:mysql://[yourhost]/[nameofyourdb]?user=[username]&password=[password]");
Now you can get an instance of a class which implements the Statement interface from the Connection instance.
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM [yourtablename]");
....
For more examples just google around a bit (JDBC, java, [nameofyourdb])
For Connector/J there is a nice documentation herer
MySQL Connector/J
Connector/J Examples
Actually, the interfaces are given by Sun and as everyone know interfaces are set of rules that will be used for a specific nature of programming and for a consistent structure. So the database vendors take that interface and will result the API which doesn't ruin the prototype. As a result every vendors implemented with same names as that interface has, irrespective of its logic.
So developers need not to worry about its implementation and must know only about the interface names.
I have worked on an abstraction for databases at work. Here is some example code
Database database = new Database(new SQL("host", "port","database", "username","password"));
List<tStd_M_lt> bases = database.select(tStd_M_lt.class, new Where(tStd_M_lt.FIELDS.ITEM_ID.getDatabaseFieldName(), OPERATOR.LIKE, "?"), "%Base%");
for (tStd_M_lt base : bases)
{
List<tShower_Base_Kit> kits = database.selectByForiegnKey(tShower_Base_Kit.class, base);
}
The project is called azirt.
Related
Here is some comparison of using DataSource and using DriverManager from https://stackoverflow.com/a/19674833/1224441
With JDBC, we can use an abstracted class, such as
java.sql.DataSource, which defines a database. However,
the MySQL DataSource and a Microsoft SQL DataSource are different
implementations. JDBC doesn't know which one you want to use.
So you use DriverManager to specify to JDBC that you want to use the
MySQL implementation, and you load that driver's class.
Say that later on you switch to Microsoft SQL. Now, all you have to do
is change the DriverManager to load the Microsoft SQL driver's class,
and all of your code that uses the abstract java.sql
classes will still work.
I found some examples of using DataSource and using DriverManager at http://zetcode.com/tutorials/jeetutorials/datasource/
But I don't see how different implementations (e.g. implementations by MySQL, and Microsoft SQL Server) would affect DataSource and DriverManager differently. Or do I misunderstand something?
When you acces you database with JDBC, you will handle java.sql.Connection, java.sql.Resultset... which are interfaces. You will actually use implementations that are specific to your database.
That way most of the code you wrote for one database can be used with another one and you don't have to learn a new API each time you need to access a new DB.
You need to specify first which implementations you need which are provided by the JDBC driver. You can do it with the old school DriverManager or with the now preferred DataSource.
DriverManager
The DriverManager is a concrete class. It isn't specific to any database. In summary it is just the place where you register your driver so you can get later all the specific implementations you need. It isn't specific by itself but it provides all the specific stuff you need.
Here is an excerpt from the example you mentioned with some of my comments.
final String url = "jdbc:mysql://localhost:3306/books";
//This line returns the Class of the Jdbc drive
//It will not be used but doing this will allow
//static initializations where it will register
//the driver to the DriverManager
Class.forName("com.mysql.jdbc.Driver");
//Here you get your connection implmentation
Connection con = DriverManager.getConnection(url, "root", "");
//MySQL specific Statement
Statement stmt = con.createStatement();
//MySQL specific ResultSet
ResultSet result = stmt.executeQuery("SELECT * FROM books");
The "trap" here is that the registration of the driver (to the DriverManager) is done during the static init done when you call the the Class.forName method.
For your information, here is the piece of code in com.mysql.jdbc.Driver doing the the driver registration in the init:
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
DataSource
Using DataSource is more suitable for external configuration. DataSource is an interface and the implementation depends directly on the database.
In your example, the Driver implementation is specified in the web.xml file.
First we define the driver to be able to find it with JNDI
<database>
<jndi-name>jdbc/mysql</jndi-name>
<driver>
<type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
<url>jdbc:mysql://localhost:3306/books</url>
<user>root</user>
<password></password>
</driver>
<database>
And then we pass the reference to the servlet :
<servlet>
<servlet-name>datasource</servlet-name>
<servlet-class>com.zetcode.DataSourceExample</servlet-class>
<init>
<data-source>${jndi:lookup('jdbc/mysql')}</data-source>
</init>
</servlet>
That way, you had not to write any specific line of code. If you change your database, (in theory) you just have to change your configuration. Not the code.
Important notes
As Kayaman mentioned in the comments calling Class.forName is no longer needed since Java 6. All you need is having the driver in your classpath.
As a reminder using DriverManager is not recommended anymore. See this excerpt from the javadoc
NOTE: The DataSource interface, new in the JDBC 2.0 API, provides another way to connect to a data source. The use of a DataSource object is the preferred means of connecting to a data source.
I am facing a use case that I have not ran into before with respect to using the jdbc template. I looked all over the web and also here, but can't find an answer to my use case.
In the current framework that I am using which was developed at the company I am currently working at, jdbc connections are readily availabe and obtained in the following format:
ConnectionManager.getInstance().getConnection(some_database_name);
The database name is a parameter provided and it can be different at times.
So in order to use the jdbc template, I created a sub class of the commons dbcp data source and added a constructor which takes in the connection above
public CommonsDBCPExtension(Connection conn) {
this.conn = conn;
}
Then I just instantiate a jdbc template and set the datasource:
this.jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(CommonsDBCPExtension);
After that so far all my tests are working. The reason I want to stick with the jdbc template is so that I can avoid all the nightmare jdbc code that I'll have to write which in my opinion is worse than what I have done so far.
So I am wondering if there is a more elegant way of doing this in spring, or this is just flat out wrong, or if it's the right approach. This is the first time I have run into this use case in my career, so a bit of help from anyone who has had experience with something like this would be greatly appreciated.
Im creating a simple DBHelper for my postgre DB using a JDBC driver.
Im wondering what are the best practices?
For example, are methods like initConnection() closeConnection() or any other, should be static one? Like:
void foo{
DBHelper.initConnection();
// do some logic, maybe:
// Data someData = DBHelper.getSomeData();
DBHelper.closeConnection();
}
Or maybe better if i will create a DBHelper object and call method for object. Like:
void foo2{
DBHelper dbhelper = new DBHelper();
dbhelper.initConnection();
// do some logic, maybe:
// Data someData = dbhelper.getSomeData();
dbhelper.closeConnection();
}
Is it matter at all?
Do i need always check if connection is open before i will try to retrive some data? What if it is close? And always try to close it in finally block?
EDIT:
in answer to #Kayaman comment:
So my foo method like this?
void foo3{
Connection conn = DBHelper.getConnection();
// do some logic, maybe:
// Statement statement = conn.createStatement();
// some stmt work
conn.close() //do i need check if stmt is closed before?
}
That will make my DBHelper class usefull only to getting connection. There will be no logic inside? (like GetInterestingRecords() or GetRecordsWithId(30) ?
Have you thought about defining the connection properties in the server config file (if it is a web app) and have the session opened for the whole application lifecycle?
Before implementing DBHelper you should check if some java libraries may satisfy your needs. If you take a look at this there are listed some libraries that seem to fit your problem.
If you decide to go on with your own custom implementation I suggest to make DBHelper a normal class with no static methods for managing the connections; the main reason is that with static methods you cannot manage multiple (i.e. connections to different databases) db connections at the same time. If you are using a java 7 implementation in your onw library you could also implement tha AutoClosable inferface in order to better manage the resource you library is managing.
I have having this problem with Java JMS when I am sending a queue to other systems and also planning to access the database to store some pictures.
I am facing this error with the compiler:
reference to connection is ambiguous,both interface
java.sql.Connection in java.sql and interface and interface javax.jms
Connection in javax.jms match Connection connection = null;
It should be quite a simple tweak to the code but I am not sure how. Any ideas?
You have to user the fully qualified class name, that is, java.sql.Connection or javax.jms.Connection. Otherwise the compiler doesn't know which connection interface you are referring to.
In JDBC we use the
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
method to load the object in memory. Then when we use the DriverManager class to get a connection to the Sql Server, the DriverManager automatically uses the appropriate drivers from the set of drivers loaded in memory. Can the DriverManager concept be compared with the Provider design pattern used in .net ? If not, then what exactly do we mean by
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
method and why don't we create the object of the sql server driver class using the new keyword ?
Class.forName("XXXDriver") invokes static block of XXXDriver.
Usually the static block invokes DriverManager.registerDriver(new XXXDriver()) to register itself to DriverManager.
Something like:
public class XXXDriver implements Driver{
static{
//Be invoked by Class.forName("XXXDriver")
DriverManager.registerDriver(new XXXDriver())
}
...
}
Unfortunately I don't know about the provider pattern in .Net. But here is what that Class.forName() magic is for.
You don't instantiate the class via newInstance(). forName() is enough. (Ok, I see the reason for instance creation in BalusC's answer.)
The JDBC specification mandates that every JDBC driver registers itself with DriverManager.registerDriver(). This is done via a static block that gets executed when the class is loaded. Class loading is initiated via Class.forName().