can we create a common database class in java - java

i want to know if we can create a common database class same like we create a connection class and just call getConnection when we need connection to be established.
Basically, i want a database manager class which can handle database operation irrespective of tablename, columncount,etc.
tablename, columnname, values to be inserted would be passed as parameters from servlet.
that way, i can reduce duplication of code. m tryin to make a simple mvc application using jsp-servlets. my database is mysql. i dont know struts, spring, hibernate.
For Example, servlet code will call(databaseManager is the class name.) :
int count=databaseManager.getCount("tableName", "columnName", "value");
and in databaseManager, there will be a function -
public static int getCount(String tableName, String[] arrC, objectArray[] arrV)
{}
similarly, for other functions.
i googled and found out that it could be done using metadata.
but i dont know how to use it.
it would be helpful if u could post code of one function for similar approach.

Check DbUtils component of Apache Commons. Also there are examples provided.

Yes, sure you can. I have done something similar (but not the same) and there can be many approaches. I think you should google more, I'm sure, that there are lot of open source applications for database management/database clients. Try to get inspiration there.
Okay, here is some code for inspiration. It is not totally generic, or what are you looking for, but I think, this could lead you somewhere. If not, throw the stone. :-)
Database provider class:
import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaProperty;
public class DatabaseProvider<T extends DatabaseObject> {
private static DatabaseProvider databaseProvider;
private static String connectionString = "";
private static String password = "";
private static String username = "";
private static boolean initialized = true;
public DatabaseProvider(){ }
public static void initDatabaseProvider() {
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
}
catch(SQLException e){
initialized = false;
e.printStackTrace();
}
connectionString = "XXX";
username = "XXX";
password = "XXX";
}
public List<T> performSimpleSelectQuery(String table, String columns, String where, Class targetObj) throws SQLException {
if(!initialized) return null;
List<T> results = new ArrayList<T>();
Constructor ct;
DatabaseObject dbo;
try {
ct = targetObj.getConstructor(null);
dbo = (DatabaseObject)ct.newInstance(null);
}
catch(Exception e){
e.printStackTrace();
return null;
}
String[] cols = columns.split(",");
String[] properties = new String[cols.length];
for(int i = 0; i < cols.length; i++){
cols[i] = cols[i].trim();
properties[i] = dbo.getMappingFromColumnName(cols[i]);
}
Connection conn = DriverManager.getConnection(connectionString, username, password);
PreparedStatement pst = conn.prepareStatement("SELECT " + columns + " FROM " + table + (where.equals("") ? "" : " WHERE " + where));
pst.execute();
ResultSet rs = pst.getResultSet();
while(rs.next()){
try {
dbo = (DatabaseObject)ct.newInstance(null);
for(int i = 0; i < cols.length; i++){
BeanUtils.setProperty(dbo, properties[i], rs.getObject(cols[i]));
}
results.add((T)dbo);
}
catch(Exception e){
e.printStackTrace();
rs.close();
pst.close();
conn.close();
return null;
}
}
rs.close();
pst.close();
conn.close();
return results;
}
public int performInsert(String columns, String values, String table) throws SQLException {
String sqlInsert = "INSERT INTO " + table + " (" + columns + ") VALUES (" + values + ")";
Connection conn = DriverManager.getConnection(connectionString, username, password);
PreparedStatement pst = conn.prepareStatement(sqlInsert);
int toReturn = 0;
try {
toReturn = pst.executeUpdate();
}
catch(Exception e){
e.printStackTrace();
pst.close();
conn.close();
return toReturn;
}
pst.close();
conn.close();
return toReturn;
}
}
Database object class:
import java.util.HashMap;
public abstract class DatabaseObject {
protected HashMap<String, String> dbToBeanMapping = new HashMap<String, String>();
public DatabaseObject() {
initialize();
}
protected abstract void initialize();
public String getMappingFromColumnName(String columnName) {
return dbToBeanMapping.get(columnName);
}
}
Example class:
public class CounterParty extends DatabaseObject {
private String name;
private int instrument;
private int partyId;
public int getPartyId() {
return partyId;
}
public void setPartyId(int partyId) {
this.partyId = partyId;
}
public CounterParty(){}
public int getInstrument() {
return instrument;
}
public void setInstrument(int instrument) {
this.instrument = instrument;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected void initialize() {
this.dbToBeanMapping.put("company_name", "name");
this.dbToBeanMapping.put("party_id", "partyId");
this.dbToBeanMapping.put("inst_id", "instrument");
}
}

Related

MYSQL JDBC java.sql.SQLException: Operation not allowed after ResultSet closed

I have a program that queries a database using different jdbc drivers. This error is specific to the MySQL driver.
Here's the basic rundown.
I have another query runner class that uses a postgresql jdbc driver that works just fine. Note the line conn.close(); this works fine on my postgresql query runner, but for this SQL runner it comes up with the error.
I have removed the line conn.close(); and this code works fine, but over time it accumulates sleeping connections in the database. How can I fix this?
New Relic is a third party application that I am feeding data to, if you dont know what it is, don't worry it's not very relevant to this error.
MAIN CLASS
public class JavaPlugin {
public static void main(String[] args) {
try {
Runner runner = new Runner();
runner.add(new MonitorAgentFactory());
runner.setupAndRun(); // never returns
}
catch (ConfigurationException e) {
System.err.println("ERROR: " + e.getMessage());
System.exit(-1);
}
catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
System.exit(-1);
}
}
}
MYSQL QUERY RUNNER CLASS
import com.newrelic.metrics.publish.util.Logger;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
public class MySQLQueryRunner {
private static final Logger logger = Logger.getLogger(MySQLQueryRunner.class);
private String connectionStr;
private String username;
private String password;
public MySQLQueryRunner(String host, long port, String database, String username, String password) {
this.connectionStr = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false";
this.username = username;
this.password = password;
}
private void logError(String message) {
logger.error(new Object[]{message});
}
private void logDebugger(String message) {
logger.debug(new Object[]{message});
}
private Connection establishConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
logError("MySQL Driver could not be found");
e.printStackTrace();
return null;
}
Connection connection = null;
try {
connection = DriverManager.getConnection(connectionStr, username, password);
logDebugger("Connection established: " + connectionStr + " using " + username);
} catch (SQLException e) {
logError("Connection Failed! Check output console");
e.printStackTrace();
return null;
}
return connection;
}
public ResultSet run(String query) {
Connection conn = establishConnection();
if (conn == null) {
logError("Connection could not be established");
return null;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
conn.close();
return rs;
} catch (SQLException e) {
logError("Failed to collect data from database");
e.printStackTrace();
return null;
}
}
}
AGENT CLASS
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import com.newrelic.metrics.publish.Agent;
public class LocalAgent extends Agent {
private MySQLQueryRunner queryRunner;
private String name;
private Map<String, Object> thresholds;
private int intervalDuration;
private int intervalCount;
public LocalAgent(String name, String host, long port, String database, String username, String password, Map<String, Object> thresholds, int intervalDuration) {
super("com.mbt.local", "1.0.0");
this.name = name;
this.queryRunner = new MySQLQueryRunner(host, port, database, username, password);
// this.eventPusher = new NewRelicEvent();
this.thresholds = thresholds;
this.intervalDuration = intervalDuration;
this.intervalCount = 0;
}
/**
* Description of query
*/
private void eventTestOne() {
String query = "select count(1) as jerky from information_schema.tables;";
ResultSet rs = queryRunner.run(query);
try {
while (rs.next()) {
NewRelicEvent event = new NewRelicEvent("localTestOne");
event.add("jerky", rs.getInt("jerky"));
event.push();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* blah
*/
private void eventTestTwo() {
String query = "SELECT maxlen FROM information_schema.CHARACTER_SETS;";
ResultSet rs = queryRunner.run(query);
try {
while (rs.next()) {
NewRelicEvent event = new NewRelicEvent("localTestTwo");
event.add("beef", rs.getString("maxlen"));
event.push();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
#Override
public void pollCycle() {
if (this.intervalCount % this.intervalDuration == 0) {
eventTestOne();
eventTestTwo();
this.intervalCount = 0;
}
// Always incrementing intervalCount, keeping track of poll cycles that have passed
this.intervalCount++;
}
#Override
public String getAgentName() {
return this.name;
}
}
The problem is that you are trying to access the ResultSet after the connection is closed.
You should open and close the connection in the method that is calling run() this way the connection will be open when you access and loop through the Resultset and close it in the finally block of the calling method.
Even better would be if you can just loop through the ResultSet in the run() method and add the data to an object and return the object, this way you can close it in the finally block of the run() method.

getting null values when trying to pass values to xml response in web service from model class

/**
* ConnectDB2.java , i'm fetching data from database and setting values to model class.
*/
package org.com.repair.spotify.repair.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.ws.rs.Path;
import org.com.repair.spotify.repair.model.RepairDetails;
/**
* #author www.javaworkspace.com
*
*/
#Path("/connectDB2")
public class ConnectDB2 {
Connection connection = null;
ResultSet resultSet = null;
Statement statement = null;
String deviceName;
String deviceModel;
String ticketId;
String issue;
String deviceType;
public ConnectDB2() {
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
connection = DriverManager.getConnection(
"jdbc:db2://localhost:50000/HELLO", "db2admin", "admin");
statement = connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM DEVICE ");
while (resultSet.next()) {
System.out.println("DEVICE BRAND:" + resultSet.getString(1)
+ " || ISSUE: " + resultSet.getString(2) + " ||MODEL:"
+ resultSet.getString(3) + "||TYPE:"
+ resultSet.getString(4));
RepairDetails Rd = new RepairDetails();
Rd.setDeviceModel(resultSet.getString(1));
Rd.setIssue(resultSet.getString(2));
Rd.setDeviceType(resultSet.getString(3));
Rd.setDeviceType(resultSet.getString(4));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/RepairDetails.java==> my Model class/
package org.com.repair.spotify.repair.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class RepairDetails {
String deviceName;
String deviceModel;
String ticketId;
String issue;
String deviceType;
public RepairDetails() {
}
public RepairDetails(String deviceName, String deviceModel,
String ticketId, String issue, String deviceType) {
super();
this.deviceName = deviceName;
this.deviceModel = deviceModel;
this.ticketId = ticketId;
this.issue = issue;
this.deviceType = deviceType;
}
public String getDeviceName() {
System.out.println("getter" + deviceName);
return deviceName;
}
public void setDeviceName(String deviceName) {
System.out.println("setter" + deviceName);
this.deviceName = deviceName;
}
public String getDeviceModel() {
return deviceModel;
}
public void setDeviceModel(String deviceModel) {
System.out.println("setter" + deviceModel);
this.deviceModel = deviceModel;
}
public String getTicketId() {
return ticketId;
}
public void setTicketId(String ticketId) {
this.ticketId = ticketId;
}
public String getIssue() {
return issue;
}
public void setIssue(String issue) {
System.out.println("setter" + issue);
this.issue = issue;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
System.out.println("setter" + deviceType);
this.deviceType = deviceType;
}
}
//the service class from where i'm trying get values from model, but i'm fetching null value which is further passed on getRepairdetails()
package org.com.repair.spotify.repair.service;
import java.util.ArrayList;
import java.util.List;
import org.com.repair.spotify.repair.db.ConnectDB2;
import org.com.repair.spotify.repair.model.*;
public class RepairService {
public RepairService() {
ConnectDB2 db = new ConnectDB2();
}
public List<RepairDetails> getRepairService()
{
System.out.println("getRepairDetails-->2");
RepairDetails Rd = new RepairDetails();
System.out.println("hey im firing");
RepairDetails RD1 = new RepairDetails(Rd.getDeviceName(),
Rd.getDeviceModel(), Rd.getIssue(), Rd.getDeviceType(),
"Mobile");
List<RepairDetails> list = new ArrayList<RepairDetails>();
list.add(RD1);
return list;
}
}
Kindly help me why null values are returned by getter ???
Let's start with examining the RepairDetails class. This one implements a POJO (Plain old Java object) and contains two constructors.
public RepairDetails()
public RepairDetails(String, String, String, String, String)
So when you create the object with the first constructor, that means you are not setting anything to the fields, that means that the values are initialized to null.
Now let's examine the RepairService class. There you have this code in the getRepairService() method.
RepairDetails Rd = new RepairDetails();
RepairDetails RD1 = new RepairDetails(Rd.getDeviceName(),
Rd.getDeviceModel(), Rd.getIssue(), Rd.getDeviceType(),
"Mobile");
List<RepairDetails> list = new ArrayList<RepairDetails>();
list.add(RD1);
Here we have the following observations:
Rd is an object created with the first constructor, so effectively the values in Rd will be null.
You are constructing RD1 with values got from Rd meaning that they will be null too.
I hope you get it now.

How to fix the result consisted of more than one row error

I wrote stored procedure in MySQL which looks like this (it works):
DELIMITER //
CREATE PROCEDURE getBrandRows(
IN pBrand VARCHAR(30),
OUT pName VARCHAR(150),
OUT pType VARCHAR(200),
OUT pRetailPrice FLOAT)
BEGIN
SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
FROM part
WHERE p_brand LIKE pBrand;
END//
DELIMITER ;
I try to return multiple results and display them. I've tried many ways described here on Stack and in Internet but that does not help me. I have edited my entire code and created a simple one so you can guys paste it and compile. It should work but with error. Here is the code:
package javamysqlstoredprocedures;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JavaMySqlStoredProcedures {
private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/"
+ "anton869_cars?noAccessToProcedureBodies=true";
private final String DB_USER = "xxx";
private final String DB_PASSWORD = "xxx";
class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {
#Override
public Void doInBackground() {
displaySql();
return null;
}
#Override
public void done() {
}
private void displaySql() {
try {
System.out.println("Connecting to MySQL database...");
Class.forName(DEFAULT_DRIVER);
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER,
DB_PASSWORD)) {
System.out.println("Connected to MySQL database");
CallableStatement cs = conn.prepareCall("{CALL getBrandRows("
+ "?, ?, ?, ?)}");
cs.setString(1, "Brand#13");
cs.registerOutParameter(2, Types.VARCHAR);
cs.registerOutParameter(3, Types.VARCHAR);
cs.registerOutParameter(4, Types.FLOAT);
boolean results = cs.execute();
while (results) {
ResultSet rs = cs.getResultSet();
while (rs.next()) {
System.out.println("p_name=" + rs.getString("p_name"));
System.out.println("p_type=" + rs.getString("p_type"));
System.out.println("p_retailprice=" + rs
.getFloat("p_retailprice"));
}
rs.close();
results = cs.getMoreResults();
}
cs.close();
} catch (SQLException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public JavaMySqlStoredProcedures() {
new CallStoredProcedureAndSaveXmlFile().execute();
}
public static void main(String[] args) {
JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
}
}
ResultSet can handle multiple records.I found some errors in your code.Try these steps
Move your all close method to finally block.
try {
//do something
} catch (Exception e) {
//do something
} finally {
try{
resultSet.close();
statement.close();
connection.close();
} catch (SQLException se) {
//do something
}
}
You can put your result into List. See sample
List<YourObject> list = new ArrayList<YourObject>();
while (rs.next()) {
YourObject obj = new Your Object();
obj.setName(rs.getString("p_name"));
obj.setType(rs.getString("p_type"));
obj.setRetailPrice(rs.getFloat("p_retailprice"));
list.add(obj);
}
Make sure your query is correct and database connection is Ok.
Don't use IN or OUT parameter if you just simply want to display result. And also you should add '%%' in your LIKE clause with the help of CONCAT function. Please try this one:
DELIMITER //
CREATE PROCEDURE getBrandRows(
pBrand VARCHAR(30)
)
BEGIN
SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
FROM part
WHERE p_brand LIKE CONCAT("%", pBrand, "%");
END//
DELIMITER ;
I am posting correct solution to everybody who have smiliar problem:
1. Corrected Stored Procedure:
DELIMITER //
CREATE PROCEDURE getBrandRows(
IN pBrand VARCHAR(30))
BEGIN
SELECT p_name, p_type, p_retailprice
FROM part
WHERE p_brand = pBrand;
END//
DELIMITER ;
2. Corrected Java code:
package javamysqlstoredprocedures;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JavaMySqlStoredProcedures {
private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/"
+ "anton869_cars?noAccessToProcedureBodies=true";
private final String DB_USER = "xxx";
private final String DB_PASSWORD = "xxx";
class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {
#Override
public Void doInBackground() {
displaySql();
return null;
}
#Override
public void done() {
}
private void displaySql() {
Connection conn = null;
CallableStatement cs = null;
ResultSet rs = null;
try {
System.out.println("Connecting to MySQL database...");
Class.forName(DEFAULT_DRIVER);
conn = DriverManager.getConnection(DB_URL, DB_USER,
DB_PASSWORD);
System.out.println("Connected to MySQL database");
cs = conn.prepareCall("{CALL getBrandRows(?)}");
cs.setString(1, "Brand#13");
boolean results = cs.execute();
while (results) {
rs = cs.getResultSet();
while (rs.next()) {
System.out.println("p_name=" + rs.getString("p_name"));
System.out.println("p_type=" + rs.getString("p_type"));
System.out.println("p_retailprice=" + rs.getFloat(
"p_retailprice"));
}
results = cs.getMoreResults();
}
} catch (SQLException | ClassNotFoundException e) {
} finally {
try {
if (rs != null ) rs.close();
if (cs != null) cs.close();
if (conn != null) conn.close();
} catch (SQLException e) {
}
}
}
public JavaMySqlStoredProcedures() {
new CallStoredProcedureAndSaveXmlFile().execute();
}
public static void main(String[] args) {
JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
}
}
Your stored procedure returns more than one row. Just correct logic behind your select query inside the stored procedure it should return only one row.
here how to return multiple value

Working with ResultSets in Java

I've ran into a problem of having to run a number of different queries on the DB (different return types, different number of columns, etc).
While writing that i started to wonder if there's a proper way of writing a helper function.
It seemed that it's really easy to write a function that returns a ResultSet.
However since it a) doesn't close connection b) doesn't close the result set it seems as a possibly working, but improper solution. Is there any place to dump in all results so that they can be returned safely.
(Only thing i could come up with, is just returning a 2D string array (after converting all data to strings) and then converting it all back)
EDIT : Sorry for not writing clear, was wondering if there's any way to just store the result of the query as is (don't need to modify it) without writing a separate method for every possible return type.
The idea behind a 2d string list is being able to store the query values as is.
Col1 Row1 | Col2 Row1 | Col3 Row1
Col1 Row2 | Col2 Row2 | Col3 Row2
EDIT 2 Thank you for replies, i guess i'll just write a small parser for it.
You shouldn't be returning resultSets, you should read the results from the resultset into some kind of container object. A ResultSet is a wrapper around a database cursor, it goes away when the connection closes. It's something you read from and close right away, not something you can pass around your application.
Look at how spring-jdbc does it. You implement a resultSetMapper that is passed to the method on the JdbcTemplate.
Several observations:
You don't need to use Spring to use spring-jdbc. However, I see very little value in reimplementing this stuff yourself.
It's not the job of the code that reads the ResultSet to open and close connections, that needs to be elsewhere.
I'd recommend looking at Spring JDBC. Don't write such a thing yourself. It's already been done, and quite well.
For example, I don't like your idea of returning a List of Strings. You lose a lot of info that way. I'd return a Map of Lists (column view) or List of Maps (row view).
If you must, here are some database utilities that would get you started.
package persistence;
import java.sql.*;
import java.util.*;
/**
* util.DatabaseUtils
* User: Michael
* Date: Aug 17, 2010
* Time: 7:58:02 PM
*/
public class DatabaseUtils {
/*
private static final String DEFAULT_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DEFAULT_URL = "jdbc:oracle:thin:#host:1521:database";
private static final String DEFAULT_USERNAME = "username";
private static final String DEFAULT_PASSWORD = "password";
*/
/*
private static final String DEFAULT_DRIVER = "org.postgresql.Driver";
private static final String DEFAULT_URL = "jdbc:postgresql://localhost:5432/party";
private static final String DEFAULT_USERNAME = "pgsuper";
private static final String DEFAULT_PASSWORD = "pgsuper";
*/
private static final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
private static final String DEFAULT_URL = "jdbc:mysql://localhost:3306/party";
private static final String DEFAULT_USERNAME = "party";
private static final String DEFAULT_PASSWORD = "party";
public static void main(String[] args) {
long begTime = System.currentTimeMillis();
String driver = ((args.length > 0) ? args[0] : DEFAULT_DRIVER);
String url = ((args.length > 1) ? args[1] : DEFAULT_URL);
String username = ((args.length > 2) ? args[2] : DEFAULT_USERNAME);
String password = ((args.length > 3) ? args[3] : DEFAULT_PASSWORD);
Connection connection = null;
try {
connection = createConnection(driver, url, username, password);
DatabaseMetaData meta = connection.getMetaData();
System.out.println(meta.getDatabaseProductName());
System.out.println(meta.getDatabaseProductVersion());
String sqlQuery = "SELECT PERSON_ID, FIRST_NAME, LAST_NAME FROM PERSON ORDER BY LAST_NAME";
System.out.println("before insert: " + query(connection, sqlQuery, Collections.EMPTY_LIST));
connection.setAutoCommit(false);
String sqlUpdate = "INSERT INTO PERSON(FIRST_NAME, LAST_NAME) VALUES(?,?)";
List parameters = Arrays.asList("Foo", "Bar");
int numRowsUpdated = update(connection, sqlUpdate, parameters);
connection.commit();
System.out.println("# rows inserted: " + numRowsUpdated);
System.out.println("after insert: " + query(connection, sqlQuery, Collections.EMPTY_LIST));
} catch (Exception e) {
rollback(connection);
e.printStackTrace();
} finally {
close(connection);
long endTime = System.currentTimeMillis();
System.out.println("wall time: " + (endTime - begTime) + " ms");
}
}
public static Connection createConnection(String driver, String url, String username, String password) throws ClassNotFoundException, SQLException {
Class.forName(driver);
if ((username == null) || (password == null) || (username.trim().length() == 0) || (password.trim().length() == 0)) {
return DriverManager.getConnection(url);
} else {
return DriverManager.getConnection(url, username, password);
}
}
public static void close(Connection connection) {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Statement st) {
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback(Connection connection) {
try {
if (connection != null) {
connection.rollback();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static List<Map<String, Object>> map(ResultSet rs) throws SQLException {
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
try {
if (rs != null) {
ResultSetMetaData meta = rs.getMetaData();
int numColumns = meta.getColumnCount();
while (rs.next()) {
Map<String, Object> row = new HashMap<String, Object>();
for (int i = 1; i <= numColumns; ++i) {
String name = meta.getColumnName(i);
Object value = rs.getObject(i);
row.put(name, value);
}
results.add(row);
}
}
} finally {
close(rs);
}
return results;
}
public static List<Map<String, Object>> query(Connection connection, String sql, List<Object> parameters) throws SQLException {
List<Map<String, Object>> results = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement(sql);
int i = 0;
for (Object parameter : parameters) {
ps.setObject(++i, parameter);
}
rs = ps.executeQuery();
results = map(rs);
} finally {
close(rs);
close(ps);
}
return results;
}
public static int update(Connection connection, String sql, List<Object> parameters) throws SQLException {
int numRowsUpdated = 0;
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
int i = 0;
for (Object parameter : parameters) {
ps.setObject(++i, parameter);
}
numRowsUpdated = ps.executeUpdate();
} finally {
close(ps);
}
return numRowsUpdated;
}
}
You can write helper functions that parse a ResultSet and convert it into an ArrayList or an array or even the fields of an object. For instance, lets say you have a table of orders and then a query returns all of the rows of that table for a particular user (customer). We could then do something like this:
static List<Order> parseOrder(ResultSet rs) {
ArrayList<Order> orderList = new ArrayList<>();
while(rs.next() ) {
Order order = new Order();
order.setID(rs.getInt(1));
order.setCustomerID(rs.getInt(2));
order.setItemName(rs.getString(3));
orderList.add(order);
}
return orderList;
}
Simply turning the result set into an array of an array of Objects would be more general, but probably less useful.
I would leave it up to the calling function to close this ResultSet and possible the PreparedStatement (or Statement) and database connection.

Junit test case for database insert method with DAO and web service

I am implementing a webservice based university management system. This system adds certain courses to database. here below is the code that I am using.
Course.java
public class Course {
private String courseName;
private String location;
private String courseId;
public String getCourseId()
{
return courseId;
}
public void setCourseId(String courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
then another file is as below
CourseDaoImpl.java
public class CourseDaoImpl implements IDao {
Connection conn = null;
Statement stmt = null;
public CourseDaoImpl(){
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/univesitydb", "root", "root");
stmt = conn.createStatement();
if (!conn.isClosed())
System.out.println("Successfully connectiod");
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
#Override
public String add(Object object) {
Course c = (Course) object ;
String courseId = c.getCourseId();
String courseName = c.getCourseName();
String location = c.getLocation();
String result = "";
int rowcount;
try {
String query = "Insert into course (courseId,courseName,location) values"
+ " ('"
+ courseId
+ "', '"
+ courseName
+ "', '"
+ location
+ "')";
rowcount = stmt.executeUpdate(query);
if (rowcount > 0) {
result = "true";
System.out.println("Course inserted successful");
} else {
result = "false:The data could not be inserted in the databse";
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
the third is the Web service file as follows which interacts with the previous two and adds data to database.
CourseService.java
package edu.service;
import edu.dao.IDao;
import edu.dao.impl.CourseDaoImpl;
import edu.db.entity.Course;
public class CourseService {
public String addCourse(String courseId, String courseName, String location)
{
Course c = new Course();
c.setCourseId(courseId);
c.setCourseName(courseName);
c.setLocation(location);
IDao dao = new CourseDaoImpl();
return dao.add(c);
}
Looking at my code listings can any body suggest me how do I write test case for my add method. I am totally beginner for JAVA, I took help from my friends to learn this java part and Now need to implement Junit test for my database methods like add course above.
Please suggest some thing that I can learn , read and use to implement Junit testing for my database methods.
This is one sample dao test using junit in spring project.
import java.util.List;
import junit.framework.Assert;
import org.jboss.tools.example.springmvc.domain.Member;
import org.jboss.tools.example.springmvc.repo.MemberDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:test-context.xml",
"classpath:/META-INF/spring/applicationContext.xml"})
#Transactional
#TransactionConfiguration(defaultRollback=true)
public class MemberDaoTest
{
#Autowired
private MemberDao memberDao;
#Test
public void testFindById()
{
Member member = memberDao.findById(0l);
Assert.assertEquals("John Smith", member.getName());
Assert.assertEquals("john.smith#mailinator.com", member.getEmail());
Assert.assertEquals("2125551212", member.getPhoneNumber());
return;
}
#Test
public void testFindByEmail()
{
Member member = memberDao.findByEmail("john.smith#mailinator.com");
Assert.assertEquals("John Smith", member.getName());
Assert.assertEquals("john.smith#mailinator.com", member.getEmail());
Assert.assertEquals("2125551212", member.getPhoneNumber());
return;
}
#Test
public void testRegister()
{
Member member = new Member();
member.setEmail("jane.doe#mailinator.com");
member.setName("Jane Doe");
member.setPhoneNumber("2125552121");
memberDao.register(member);
Long id = member.getId();
Assert.assertNotNull(id);
Assert.assertEquals(2, memberDao.findAllOrderedByName().size());
Member newMember = memberDao.findById(id);
Assert.assertEquals("Jane Doe", newMember.getName());
Assert.assertEquals("jane.doe#mailinator.com", newMember.getEmail());
Assert.assertEquals("2125552121", newMember.getPhoneNumber());
return;
}
#Test
public void testFindAllOrderedByName()
{
Member member = new Member();
member.setEmail("jane.doe#mailinator.com");
member.setName("Jane Doe");
member.setPhoneNumber("2125552121");
memberDao.register(member);
List<Member> members = memberDao.findAllOrderedByName();
Assert.assertEquals(2, members.size());
Member newMember = members.get(0);
Assert.assertEquals("Jane Doe", newMember.getName());
Assert.assertEquals("jane.doe#mailinator.com", newMember.getEmail());
Assert.assertEquals("2125552121", newMember.getPhoneNumber());
return;
}
}
The design of your classes will make it hard to test them. Using hardcoded connection strings or instantiating collaborators in your methods with new can be considered as test-antipatterns. Have a look at the DependencyInjection pattern. Frameworks like Spring might be of help here.
To have your DAO tested you need to have control over your database connection in your unit tests. So the first thing you would want to do is extract it out of your DAO into a class that you can either mock or point to a specific test database, which you can setup and inspect before and after your tests run.
A technical solution for testing db/DAO code might be dbunit. You can define your test data in a schema-less XML and let dbunit populate it in your test database. But you still have to wire everything up yourself. With Spring however you could use something like spring-test-dbunit which gives you lots of leverage and additional tooling.
As you call yourself a total beginner I suspect this is all very daunting. You should ask yourself if you really need to test your database code. If not you should at least refactor your code, so you can easily mock out all database access. For mocking in general, have a look at Mockito.
#Test
public void testSearchManagementStaff() throws SQLException
{
boolean res=true;
ManagementDaoImp mdi=new ManagementDaoImp();
boolean b=mdi.searchManagementStaff("abc#gmail.com"," 123456");
assertEquals(res,b);
}
/*
public class UserDAO {
public boolean insertUser(UserBean u) {
boolean flag = false;
MySqlConnection msq = new MySqlConnection();
try {
String sql = "insert into regis values(?,?,?,?,?)";
Connection connection = msq.getConnection();
PreparedStatement statement = null;
statement = (PreparedStatement) connection.prepareStatement(sql);
statement.setString(1, u.getname());
statement.setString(2, u.getlname());
statement.setString(3, u.getemail());
statement.setString(4, u.getusername());
statement.setString(5, u.getpasswords());
statement.executeUpdate();
flag = true;
} catch (Exception e) {
} finally {
return flag;
}
}
public String userValidate(UserBean u) {
String login = "";
MySqlConnection msq = new MySqlConnection();
try {
String email = u.getemail();
String Pass = u.getpasswords();
String sql = "SELECT name FROM regis WHERE email=? and passwords=?";
com.mysql.jdbc.Connection connection = msq.getConnection();
com.mysql.jdbc.PreparedStatement statement = null;
ResultSet rs = null;
statement = (com.mysql.jdbc.PreparedStatement) connection.prepareStatement(sql);
statement.setString(1, email);
statement.setString(2, Pass);
rs = statement.executeQuery();
if (rs.next()) {
login = rs.getString("name");
} else {
login = "false";
}
} catch (Exception e) {
} finally {
return login;
}
}
public boolean getmessage(UserBean u) {
boolean flag = false;
MySqlConnection msq = new MySqlConnection();
try {
String sql = "insert into feedback values(?,?)";
Connection connection = msq.getConnection();
PreparedStatement statement = null;
statement = (PreparedStatement) connection.prepareStatement(sql);
statement.setString(1, u.getemail());
statement.setString(2, u.getfeedback());
statement.executeUpdate();
flag = true;
} catch (Exception e) {
} finally {
return flag;
}
}
public boolean insertOrder(cartbean u) {
boolean flag = false;
MySqlConnection msq = new MySqlConnection();
try {
String sql = "insert into cart (product_id, email, Tprice, quantity) values (?,?,2000,?)";
Connection connection = msq.getConnection();
PreparedStatement statement = null;
statement = (PreparedStatement) connection.prepareStatement(sql);
statement.setString(1, u.getpid());
statement.setString(2, u.getemail());
statement.setString(3, u.getquantity());
statement.executeUpdate();
flag = true;
} catch (Exception e) {
System.out.print("hi");
} finally {
return flag;
}
}
}

Categories