Store the results of ResultSet in a list - mysql

My goal is to centralize all the interactions with my MySql database in a single class (e.g. SqlUtils). I basically want to maintain access to ResultSet or a similar class even after the connection is closed. The following way doesn't work as after my business method receives the ResultSet, an exception is thrown because the underlying connection is already closed. I want to emphasize that opening and closing a connection to the database has to take place inside getResultSet().
public ResultSet getResultSet(String sql) {
try (Connection conn = getConnection();){
return conn.createStatement().executeQuery(sql);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
What I'm now thinking to do is something like this:
public List<ResultHolder> getResultSet(String sql) {
List<ResultHolder> list = new LinkedList<>();
try (Connection conn = getConnection();
ResultSet res = conn.createStatement().executeQuery(sql);) {
while(res.next()) {
list.add(res.convertToResultHolder());
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
Is there any class that does what I need, which I expressed as ResultHolder.

If you want to have access to all the resultset data even after connection is closed then I would suggest following:
public List<Map<String, Object>> getResultSet(String sql) {
// this list will hold all the data returned from resultset
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
try (Connection conn = getConnection();
ResultSet rs = conn.createStatement().executeQuery(sql);) {
while(rs.next()) {
// this map corresponds to each row of the resultset
// key: column-name, value: column-value
Map<String, Object> row = new LinkedHashMap<String, Object>();
// populate each row using resultset's Meta data
ResultSetMetaData meta = rs.getMetaData();
for (int i=1; i<=meta.getColumnCount(); i++)
row.put(meta.getColumnName(i), rs.getObject(i));
rows.add(row);
}
} catch (Exception e) {
e.printStackTrace();
}
return rows;
}

Related

Convert all the mysql table data into JSON in spring boot

I want to just specify the table name and it will automatically convert all of its data to JSON Format
I have tried a code that is storing the data from table into JSON using JDBC .
public class DataBaseToJson {
public static ResultSet RetrieveData() throws Exception {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
String mysqlUrl = "jdbc:mysql://localhost/studentsDB?autoReconnect=true&useSSL=false";
Connection con = DriverManager.getConnection(mysqlUrl, "root", "root");
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("Select * from students");
return resultSet;
}
public static void main(String args[]) throws Exception {
JSONObject jsonObject = new JSONObject();
JSONArray array = new JSONArray();
ResultSet resultSet = RetrieveData();
while (resultSet.next()) {
JSONObject record = new JSONObject();
record.put("students ID", resultSet.getInt("students_id"));
record.put("students Name", resultSet.getString("students_name"));
array.add(record);
}
jsonObject.put("students Information", array);
try {
FileWriter file = new FileWriter("output.json");
file.write(jsonObject.toJSONString());
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I don't want to specify the fileds in a file. I want to make it generic so that we could only put the table name and it will automatically convert all the data from that table and save into a JSON file.
public static void main(String args[]) throws Exception {
String tableName = "books";
Connection connection = createConnection();
JSONArray array = new JSONArray();
JSONObject jsonObject = new JSONObject();
List<String> columns = loadColumns(connection, tableName);
ResultSet dataSet = loadData(connection, tableName);
while (dataSet.next()) {
JSONObject record = new JSONObject();
for (String column : columns) {
record.put(column, dataSet.getObject(column));
}
array.add(record);
}
jsonObject.put(tableName, array);
try {
FileWriter file = new FileWriter("output.json");
file.write(jsonObject.toJSONString());
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static Connection createConnection() throws SQLException {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
String mysqlUrl = "jdbc:mysql://localhost/library?autoReconnect=true&useSSL=false";
Connection connection = DriverManager.getConnection(mysqlUrl, "root", "root");
return connection;
}
public static List<String> loadColumns(Connection connection, String tableName) throws SQLException {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT COLUMN_NAME FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_NAME LIKE '"+tableName+"'");
List<String> columnsName = new ArrayList<String>();
while(resultSet.next()) {
columnsName.add(resultSet.getString("COLUMN_NAME"));
}
return columnsName;
}
public static ResultSet loadData(Connection connection, String tableName) throws SQLException {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("Select * from "+tableName+"");
return resultSet;
}
You can select list of columns for given table using INFORMATION_SCHEMA:
SELECT COLUMN_NAME FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE TABLE_NAME LIKE 'table_name'
Now, convert ResultSet from above query to List<String> of column names. After that we can use it to convert final ResultSet to JSON Object.
Pseudocode:
Connection connection = createConnection();
List<String> columns = loadColumns(connection, tableName);
ResultSet dataSet = loadData(connection, tableName);
while (dataSet.next()) {
JSONObject record = new JSONObject();
for (String column : columns) {
record.put(column, dataSet.getObject(column));
}
array.add(record);
}
// save array to file
When ResultSet is huge we should consider to use Streaming API from Jackson or Gson libraries to avoid "out of memory" problem.
See also:
How to get database structure in MySQL via query
Jackson Streaming API
Jackson - Processing model: Streaming API
Gson Streaming
Update
It looks like we do not event need to select column names using extra SQL query because ResultSet has getMetaData method:
Retrieves the number, types and properties of this ResultSet object's
columns.
See also:
ResultSetMetaData class

MySQL connection pooling with JERSEY

I'm developping a RESTful API with Jersey and MySQL.
I'm actually using the JDBC driver to connect to the database and I create a new connection everytime I want to acess it. As it clearly is a memory leakage, I started to implement the ServletContextClassclass but I don't know how to call the method when I need to get the result of a SQL query.
Here is how I did it wrong:
DbConnection.java
public class DbConnection {
public Connection getConnection() throws Exception {
try {
String connectionURL = "jdbc:mysql://root:port/path";
Connection connection = null;
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
return connection;
}
catch (SQLException e) {
throw e;
}
}
}
DbData.java
public ArrayList<Product> getAllProducts(Connection connection) throws Exception {
ArrayList<Product> productList = new ArrayList<Product>();
try {
PreparedStatement ps = connection.prepareStatement("SELECT id, name FROM product");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Product product = new Product();
product.setId(rs.getInt("id"));
product.setName(rs.getString("name"));
productList.add(product);
}
return productList;
} catch (Exception e) {
throw e;
}
}
Resource.java
#GET
#Path("task/{taskId}")
#Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(#PathParam("taskId") int taskId) throws Exception {
try {
DbConnection database= new DbConnection();
Connection connection = database.getConnection();
Task task = new Task();
DbData dbData = new DbData();
task = dbData.getTask(connection, taskId);
return Response.status(200).entity(task).build();
} catch (Exception e) {
throw e;
}
}
Here is where I ended up trying to implement the new class:
ServletContextClass.java
public class ServletContextClass implements ServletContextListener {
public Connection getConnection() throws Exception {
try {
String connectionURL = "jdbc:mysql://root:port/path";
Connection connection = null;
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
return connection;
} catch (SQLException e) {
throw e;
}
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
DbConnection database = new DbConnection();
try {
Connection connection = database.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
//con.close ();
}
}
But problem is, I don't know what to do next. Any help? Thanks
You need to set the Connection variable as an attribute of the ServletContext. Also, I would recommend using connection as a static class variable so you can close it in the contextDestroyed method.
You can retrieve the connection attribute in any of your servlets later on for doing your DB operations.
public class ServletContextClass implements ServletContextListener {
public static Connection connection;
public Connection getConnection(){
try {
String connectionURL = "jdbc:mysql://root:port/path";
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root", "password");
} catch (SQLException e) {
// Do something
}
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("ServletContextListener started");
getConnection();
arg0.getServletContext().setAttribute("connection", connection);
}
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
try{
if(connection != null){
connection.close();
}
}catch(SQLException se){
// Do something
}
}
}
Finally access your connection attribute inside your Servlet (Resource). Make sure you pass #Context ServletContext to your Response method so you can access your context attributes.
#GET
#Path("task/{taskId}")
#Consumes(MediaType.APPLICATION_JSON)
public Response getInfos(#PathParam("taskId") int taskId, #Context ServletContext context) throws Exception {
try {
Connection connection = (Connection) context.getAttribute("connection");
Task task = new Task();
DbData dbData = new DbData();
task = dbData.getTask(connection, taskId);
return Response.status(200).entity(task).build();
} catch (Exception e) {
throw e;
}
}
Now that we have solved your current issue, we need to know what can go wrong with this approach.
Firstly, you are only creating one connection object which will be used everywhere. Imagine multiple users simultaneously accessing your API, the single connection will be shared among all of them which will slow down your response time.
Secondly, your connection to DB will die after sitting idle for a while (unless you configure MySql server not to kill idle connections which is not a good idea), and when you try to access it, you will get SQLExceptions thrown all over. This can be solved inside your servlet, you can check if your connection is dead, create it again, and then update the context attribute.
The best way to go about your Mysql Connection Pool will be to use a JNDI resource. You can create a pool of connections which will be managed by your servlet container. You can configure the pool to recreate connections if they go dead after sitting idle. If you are using Tomcat as your Servlet Container, you can check this short tutorial to get started with understanding the JNDI connection pool.

how to insert settooltiptext for one vertex retrieved from MYSQLdatabase

I have developed a MySQL database with 3 different columns. Among three columns, I used 2 columns to develop a network using JUNG. Now if I place a mouse over the vertex, the corresponding information from the third column should be displayed. I have tried with the following code with the help of setVertexToolTipTransformer. But nothing is displayed as an answer.
vv.setVertexToolTipTransformer(new Transformer<String, String>() {
public String transform(String v) {
try {
String bb = "SELECT * FROM interr'";
Statement pest = connection.createStatement();
ResultSet v1 = pest.executeQuery(bb);
while(v1.next())
v= v1.getString("Pubchem_ID");
return "PUBMED:"+v.toString();
}
catch (Exception e1) {
JOptionPane.showMessageDialog(null, e1);
}
return null;
}
});
Where should i edit my code? Can anyone pls help me with this?
I got the output with the following output
vv.setVertexToolTipTransformer(new Transformer<String, String>() {
public String transform(String v) {
try {
String bb = "SELECT * FROM interr";
Statement pest = connection.createStatement();
ResultSet v1 = pest.executeQuery(bb);
while(v1.next())
if(v.toString().equals(v1.getString("Mole1")))
na[i] = v1.getString("Pubchem_ID");
System.out.println(na[i]);
v=na[i].toString();
return "PUBMED:"+v.toString();
}
catch (Exception e1) {
JOptionPane.showMessageDialog(null, e1);
}
return null;
}
});

How to get data from MYSQL database

I have a database named as "test" in which I have a table named as "first" which contains raw data, I want to get this table data. What should be the prepare statement I have to use in order to get data from table "first" ? Below is the code I am trying. Any help or guidance would be appreciable.
#Path("/database") // Specific URL
#GE
#Produces(MediaType.TEXT_PLAIN)
public String returnDB_Status() throws Exception {
PreparedStatement query = null;
String result = null;
Connection conn = null;
try {
conn = mysql_prac.dbConn().getConnection(); // this works fine ...
query = conn.prepareStatement("SELECT * from first" ); // Table named as "first" is placed inside the connected database.
ResultSet rs = query.executeQuery();
result = "Data received : " + rs;
query.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null)
conn.close();
}
return result;
}
and the source code used get a connection
public class mysql_prac {
private static DataSource mysql_prac = null;
private static Context context = null;
public static DataSource dbConn() throws Exception {
if (mysql_prac != null) {
return mysql_prac;
}
try {
if (context == null) {
context = new InitialContext();
}
mysql_prac = (DataSource) context.lookup("JDBC_ref"); //JNDI ID (JDBC_REF)
} catch (Exception e) {
e.printStackTrace();
}
return mysql_prac;
}
}
You must loop through the ResultSet to get the fields of each row. So I made the following edit together with some comments.Please notice the comments.
try {
conn = mysql_prac.dbConn().getConnection(); // this works fine ...
query = conn.prepareStatement("SELECT * from first" ); // Table named as "first" is placed inside the connected database.
ResultSet rs = query.executeQuery();//You must loop through the results set to get the fields of each row
while(rs.next()){
String dbUserID = rs.getString("column1");//this is just an example to retrieve all data in the column called 'column1'
result = "Data received : " + dbUserID;
System.out.println(result);
}
query.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null)
conn.close();
}

Retrieving data from mysql in Java

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try
{
Class.forName("java.sql.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql", "root", "parin");
Statement stmt=con.createStatement();
String query="Select * from Liblogin;";
ResultSet rs=stmt.executeQuery(query);
String username=rs.getString("username");
String password=rs.getString("password");
rs.close();
stmt.close();
con.close();
String enteredUsername=t1.getText().toString();
String enteredPassword = new String(t2.getText());
if(enteredUsername.contentEquals(username)&&enteredPassword.contentEquals(password))
{
Homepage a=new Homepage();
a.setVisible(true);
this.dispose();
}
else
{
JOptionPane.showMessageDialog(this,"Incorrect name and password.");
}
}
catch(Exception e)
{
JOptionPane.showMessageDialog(this, e);
}
}
I am trying to retrieve my password and username from mysql database.But unable to do so because of some exception(Sql exception:Before start of result set.).
You need to call rs.first(); or rs.next(); before trying to read the values from a ResultSet row.
http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#first%28%29
Calling rs.next(); is especially handy in a while-loop to process all the rows in the ResultSet.
// Get a result set from SQL query
while (rs.next()) {
// Process this row
}