Reputation: 426
I am creating a polling program in java using TimerTask for to send email and other notifications automatically. Now this program every second check the database for any new data available.
Now i am creating connection like below
Connector class its holds database details and return a connection.
public class Connector implements Serializable {
private static final long serialVersionUID = 1L;
private ResourceBundle prop = ResourceBundle.getBundle("dbdetails");
public Connection getConnection() throws Exception {
Connection con;
Class.forName((String) prop.getString("DB_DRIVER"));
con = DriverManager.getConnection((String) prop.getString("DB_URL"),
(String) prop.getString("DB_USER"),
(String) prop.getString("DB_PASS"));
return con;
}
}
My polling class
public class EmailPoller extends TimerTask {
private static Logger logger = Logger.getLogger(EmailPoller.class);
private Connector connector = new Connector();
@Override
public void run() {
Connection con = null;
PreparedStatement ps = null, ps1 = null;
ResultSet rs = null;
try {
con = connector.getConnection();
ps = con.prepareStatement("select to_addr,subject,content,id from email_notification where status='A'");
ps1 = con
.prepareStatement("update email_notification set status='I' where id=?");
rs = ps.executeQuery();
while (rs.next()) {
Boolean b = Mailer.sendMail(rs.getString(1), rs.getString(2),
rs.getString(3));
if (b) {
ps1.setInt(1, rs.getInt(4));
ps1.executeUpdate();
}
}
} catch (Exception ex) {
logger.info("Email Poller Error : " + ex);
} finally {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (ps1 != null) {
ps1.close();
}
if (con != null) {
con.close();
}
} catch (Exception ex) {
logger.info("Email Poller Error : " + ex);
}
}
}
}
after send a email i am updating a flag. Mailer is sending mail perfectly.
Whether this is a correct approach to check the database for data or any other best way is there to connect to the database?
Upvotes: 0
Views: 1620
Reputation: 19700
Since you need to poll the database at a particular time period,
- you should never create a connection every time you seek for something in the database. Create a connection once and reuse
it, or let DataSource
handle everything. You just request DataSource a connection and it gives you a connection.
You could slightly modify your Connector
class as below to allow DataSource Implementations to handle connection pooling.
The below example uses the MySql Implementation of the DataSource interface
. You could however change the implementations depending on what database you work on, by simply adding the corresponding jar to your classpath.
class Connector implements Serializable {
private static final long serialVersionUID = 1L;
private static ResourceBundle prop = ResourceBundle.getBundle("dbdetails");
private static MysqlDataSource dataSource = null;
// Dont allow any instance of this class
private Connector(){
}
private static void initDataSource()
{
try
{
dataSource = new MysqlDataSource();
dataSource.setURL(prop.getString("DB_URL"));
dataSource.setUser(prop.getString("DB_USER"));
dataSource.setPassword(prop.getString("DB_PASS"));
}
catch (SQLException e) {
// handle the Exception according to your application demand
}
}
/*
* Return a connection from the datasource pool
*/
public static Connection getConnection() throws Exception {
if(dataSource == null)
{
initDataSource();
}
return dataSource.getConnection();
}
}
Although the above becomes more efficient, it is more suitable for web applications
where a large number of requests need to be handled and connections to be pooled. Since your program is a standalone code
, you could ignore
connection pooling and simply go ahead just ensuring that your application has only one connection at any time. You could modify the Connector class as below:
class Connector implements Serializable {
private static final long serialVersionUID = 1L;
private static ResourceBundle prop = ResourceBundle.getBundle("dbdetails");;
private static Connection con = null;
// Dont allow any instance to be created for this class
private Connector(){
}
private static void initConnection() throws Exception
{
Class.forName((String) prop.getString("DB_DRIVER"));
con = DriverManager.getConnection((String) prop.getString("DB_URL"),
(String) prop.getString("DB_USER"),
(String) prop.getString("DB_PASS"));
}
public static Connection getConnection() throws Exception {
if(con == null)
{
initConnection();
}
return con;
}
}
get the connection as: Connector.getConnection()
, following a singleton
pattern.
Upvotes: 1
Reputation: 1381
I don't believe yours is the most efficient way of getting connections. Read about Connection pools and from your timer task, acquire a connection from the pool which would be more efficient and makes your job a lot easier in terms of managing the connections.
For starters you can check : this question
Upvotes: 0