package Simple;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.text.*;
public class CurrentProg {
//connecting to the database
private static final String DB_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_CONNECTION ="jdbc:mysql://localhost:3306/db?autoReconnect=true";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "root";
static Connection dbConnection = null;
static Statement statement = null;
static int total=1;
//Searching between startdate and enddate
public static java.util.LinkedList searchBetweenDates(java.util.Date startDate, java.util.Date endDate) {
java.util.Date begin = new Date(startDate.getTime());
java.util.LinkedList list = new java.util.LinkedList();
list.add(new Date(begin.getTime()));
java.util.Date end = new Date(endDate.getTime());
endDate.setTime(endDate.getTime() + 24*3600*1000);
Calendar cal = Calendar.getInstance();
cal.setTime(begin);
dbConnection = getDBConnection();
while(begin.compareTo(endDate)<0){
begin = new Date(begin.getTime() + 86400000);
list.add(new Date(begin.getTime()));
Timestamp timestamp = new Timestamp(new Date().getTime());
//For a single day calculation: 24hours*60mins=1440 /2 (2 mins time difference as per the requirement) = 720
for (int j = 0; j < 720; j++) {
cal.add(Calendar.MINUTE, 2);
timestamp = new Timestamp(cal.getTime().getTime());
String S = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);
String[] parts = S.split(" ");
String date=parts[0];
String time=parts[1];
cal.getTime().toString();
// To create data loop into a List
List<String> records = new ArrayList<String>();
StringBuffer record = new StringBuffer();
for (int i = 1; i <= total; i++) {
records = new ArrayList<String>(total);
int a2 = 220 + j % 31; // 230 - 244 by 1
String wString = Integer.toString(a2);
String a = String.valueOf(a2);
double b2 = 0.00 + j % 3.7 ; // 1.3 - 3.9 by 0.1
String aString = Double.toString(b2);
String b = String.valueOf(b2);
b = b.substring(0, Math.min(b.length(), 5));
record.delete(0, record.length());
record.append(a + "," + b + ",'"+ date + "', '"+ time + "'");
record.append("\t\t");
record.append("\n");
records.add(record.toString());
//Insert Query
String insertTableSQL = "INSERT INTO cmd1"
+ "(a, b, date, time) " + "VALUES"
+ "("+record.toString()+")";
System.out.println("insertTableSQL - " + insertTableSQL); // Statement.executeUpdate(insertTableSQL);
try {
statement = dbConnection.createStatement();
statement.executeUpdate(insertTableSQL);
System.out.println("Record is inserted into Db table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
try {
// dbConnection = getDBConnection();
statement = dbConnection.createStatement();
statement.executeUpdate(insertTableSQL);
System.out.println("Record is inserted into Db table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
finally {
// httpPost.releaseConnection()
try{
if(statement!=null)
statement.close();
}
finally{
}
try{
if(dbConnection!=null)
dbConnection.close();
}
finally{
}
}
}
}
}
return list;
}
#SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
//To enter startDate and enddate
// EntityManagerFactory.getCache().evictAll;
SimpleDateFormat startDate=new java.text.SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat endDate=new java.text.SimpleDateFormat("yyyy-MM-dd");
java.util.LinkedList hitList = searchBetweenDates(
startDate.parse("2016-01-01"),
endDate.parse("2016-03-01"));
String[] combo = new String[hitList.size()];
for(int i=0; i<hitList.size(); i++)
combo[i] = new java.text.SimpleDateFormat("yyyy-MM-dd").format(((java.util.Date)hitList.get(i)));
}
private static void insertRecordIntodb() {
//
}
private static Connection getDBConnection() {
Connection dbConnection = null;
try {
Class.forName(DB_DRIVER);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
try {
dbConnection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
return dbConnection;
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return dbConnection;
}
}
Server connection failure during transaction. Due to underlying exception: 'java.net.SocketException: java.net.SocketException: No buffer space available (maximum connections reached?): connect'.
** BEGIN NESTED EXCEPTION **
java.net.SocketException
MESSAGE: java.net.SocketException: No buffer space available (maximum connections reached?): connect
STACKTRACE:
java.net.SocketException: java.net.SocketException: No buffer space available (maximum connections reached?): connect
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:156)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:276)
at com.mysql.jdbc.Connection.createNewIO(Connection.java:2717)
at com.mysql.jdbc.Connection.<init>(Connection.java:1509)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:266)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at Simple.CurrentProg.getDBConnection(CurrentProg.java:186)
at Simple.CurrentProg.searchBetweenDates(CurrentProg.java:126)
at Simple.CurrentProg.main(CurrentProg.java:164)
** END NESTED EXCEPTION **
Attempted reconnect 3 times. Giving up.
Exception in thread "main" java.lang.NullPointerException
at Simple.CurrentProg.searchBetweenDates(CurrentProg.java:137)
at Simple.CurrentProg.main(CurrentProg.java:164)
Here I am trying to connect java program with database but when i am trying to insert large data say for 1 month so its only fetching 16000 records not more than that i want the data should be inserted as per the given date range what should i do to get that . In stacktrace its showing an exception as no buffer space available maximum connection reached. Thanks In advance
Here is the modified code. I removed a lot of code which is not necessary:
public static LinkedList<Date> searchBetweenDates(Date startDate, Date endDate) throws SQLException {
Date begin = new Date(startDate.getTime());
LinkedList<Date> list = new LinkedList<Date>();
list.add(new Date(begin.getTime()));
endDate.setTime(endDate.getTime() + 24 * 3600 * 1000);
Calendar cal = Calendar.getInstance();
cal.setTime(begin);
dbConnection = getDBConnection();
PreparedStatement ps = dbConnection.prepareStatement("INSERT INTO cmd1(aaaa, bbbb, datee, timee) VALUES(?, ?, ?, ?)");
while (begin.compareTo(endDate) < 0) {
begin = new Date(begin.getTime() + 86400000);
list.add(new Date(begin.getTime()));
Timestamp timestamp = new Timestamp(new Date().getTime());
// For a single day calculation: 24hours*60mins=1440 /2 (2 mins time
// difference as per the requirement) = 720
for (int j = 0; j < 720; j++) {
cal.add(Calendar.MINUTE, 2);
timestamp = new Timestamp(cal.getTime().getTime());
String S = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);
String[] parts = S.split(" ");
String date = parts[0];
String time = parts[1];
cal.getTime().toString();
// To create data loop into a List
for (int i = 1; i <= total; i++) {
int a2 = 220 + j % 31; // 230 - 244 by 1
String a = String.valueOf(a2);
double b2 = 0.00 + j % 3.7; // 1.3 - 3.9 by 0.1
String b = String.valueOf(b2);
b = b.substring(0, Math.min(b.length(), 5));
ps.setString(1, a);
ps.setString(2, b);
ps.setString(3, date);
ps.setString(4, time);
ps.execute();
}
}
}
if (ps != null)
ps.close();
if (dbConnection != null)
dbConnection.close();
return list;
}
What I changed:
I removed your try/catch's because I wanted to make the code short so that I can edit it here easily. But you should handle exception correctly. And don't swallow exceptions ever. I mean the following is no go:
} catch (SQLException e) {
System.out.println(e.getMessage());
}
It is very bad Idea because you'll not see the real cause of the problem in this case; at least do e.printStackTrace() eventhough it is not recommended in a real project.
I exchanged the Statement object for PreparedStatement because it is much more efficient.
Removed package names and put import statements instead because it is not necessary to do so unless you have different classes from different packages with the same name.
I changed column names because my DB does not want to accept them. Column names like a are very bad. Choose instead descriptive names so that you might understand what it is for a couple of months later. Don't use column names like date because they are reserved words for some databases systems I know.
Don't create database resources like Connection in a loop unless it is absolutely needed! Otherwise, your program will go out of resources because these resources are very expensive! That is exactly what you are experiencing right now.
Hope it helps, otherwise, drop me a comment.
Related
For a simulation/mining on graph data I need to write thousands of data at once into a postgresql 9.5 Database with high performance. Currently I'm doing that with prepared statements and "row by row INSERTs". It works fine - but too slow. I couldn't find anything about how to write data from a collection (array, vector or ArrayList) with the Copy statement via CopyManager into a Postgresql DB Table. I would be grateful to get a simple example. How to deal with data types? CopyManager does not request for any data types.
My current Code:
package io;
import db.PostgresConnector;
import entitiesP.Edge;
import entitiesP.Graph;
import entitiesP.Node;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
public class DbLogger {
public DbLogger(Graph g, int simNr) throws Exception {
Connection conn = new PostgresConnector().getConnection();
//1. Graph Data File:
//-------------------------------------------------
//Filename und Header:
long timestamp = getTimeStamp();
//Daten:
logGraphData(conn, simNr,
g.getNodes().size(),
g.getEdges().size(),
g.getRadiusAndDiameter()[0],
g.getRadiusAndDiameter()[1],
g.getRadiusAndDiameter()[2],
Node.maxDegree,
//new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(g.getSimStartTime()),
g.getSimStartTime(),
timestamp);
//2. Node Data File:
//-------------------------------------------------
//Daten einsammeln:
for (Node n: g.getNodes()){
logNodeData( conn, simNr ,
n.getId(),
n.getDegree(),
n.getClusteringCoefficient(),
timestamp);
}
//3. RelationData File:
//-------------------------------------------------
int[][] distance = g.getDistanceMatrix().clone();
//AdMatrix dist = new AdMatrix(distance);
//dist.printAdMatrix();
Object[] edges = g.getEdges().toArray();
//adjacency nodes
int numNodes = g.getNodes().size();
int numEdges = g.getEdges().size();
//Edges:
for (int i=0; i < edges.length; i++){
Object[] nodes = ((Edge) edges[i]).getNodes().toArray(); //pair of nodes of an edge
//pairs A--B
logRelationData(conn, simNr ,
((Node) nodes[0]).getId() ,
((Node) nodes[1]).getId() ,
distance[((Node) nodes[0]).getId() -1][((Node) nodes[1]).getId() -1] ,
((Edge) edges[i]).getTieStrength() ,
((Edge) edges[i]).getNeighborhoodOverlap(((Node) nodes[0]),((Node) nodes[1])) ,
timestamp
);
//pairs B--A
logRelationData(conn, simNr ,
((Node) nodes[1]).getId() ,
((Node) nodes[0]).getId() ,
distance[((Node) nodes[0]).getId() -1][((Node) nodes[1]).getId() -1] ,
((Edge) edges[i]).getTieStrength() ,
((Edge) edges[i]).getNeighborhoodOverlap(((Node) nodes[0]),((Node) nodes[1])) ,
timestamp
);
//end edges----------------------------
}
//System.out.println("NumNodes: " + numNodes);
//non-adjacent nodes
for (int i=0; i < numNodes; i++){
for (int j=0; j < numNodes; j++){
if (distance[i][j] != 1 && i != j ){
logRelationData(conn, simNr,
(i+1),
(j+1),
(distance[i][j]==0? 999 : distance[i][j]) , //0 auf infinity setzen (999)
-1,
-1,
timestamp
);
}
}
}
conn.close();
}
private static void logGraphData(Connection con, int sim_no, int numberOfNodes, int numberOfEdges, int radius, int diameter, int effDiameter, int maxDegree, long startTime, long timestamp) throws SQLException{
PreparedStatement preStmt = con.prepareStatement("INSERT INTO public.GRAPH_DATA (" + "SIM_NO,NUMBER_OF_NODES,NUMBER_OF_EDGES,RADIUS,DIAMETER,EFF_DIAMETER,MAX_DEGREE,START_TIME,TIME_STAMP) VALUES (?,?,?,?,?,?,?,?,?)");
preStmt.setInt(1, sim_no);
preStmt.setInt(2, numberOfNodes);
preStmt.setInt(3, numberOfEdges);
preStmt.setInt(4, radius);
preStmt.setInt(5, diameter);
preStmt.setInt(6, effDiameter);
preStmt.setInt(7, maxDegree);
preStmt.setTimestamp(8, new Timestamp(startTime));
preStmt.setTimestamp(9, new Timestamp(timestamp));
preStmt.executeUpdate();
preStmt.close();
//con.close();
}
private static void logNodeData(Connection con, int sim_no, int nodeId, int degree, double clusteringCoeff, long timeStamp) throws SQLException{
PreparedStatement preStmt = con.prepareStatement("INSERT INTO public.NODE_DATA (" + "SIM_NO,NODE_ID,DEGREE,CLUSTERING_COEFFICIENT,TIME_STAMP) VALUES (?,?,?,?,?)");
preStmt.setInt(1, sim_no);
preStmt.setInt(2, nodeId);
preStmt.setInt(3, degree);
preStmt.setDouble(4, clusteringCoeff);
preStmt.setTimestamp(5, new Timestamp(timeStamp));
preStmt.executeUpdate();
preStmt.close();
//con.close();
}
private static void logRelationData(Connection con, int sim_no, int nodeId1, int nodeId2, int distance, int tieStrength, double neighborhoodOverlap, long timeStamp) throws SQLException{
PreparedStatement preStmt = con.prepareStatement("INSERT INTO public.RELATION_DATA (" + "SIM_NO,NODE_ID1,NODE_ID2,DISTANCE,TIE_STRENGTH,NEIGHBORHOOD_OVERLAP,TIME_STAMP) VALUES (?,?,?,?,?,?,?)");
preStmt.setInt(1, sim_no);
preStmt.setInt(2, nodeId1);
preStmt.setInt(3, nodeId2);
preStmt.setInt(4, distance);
preStmt.setInt(5, tieStrength);
preStmt.setDouble(6, neighborhoodOverlap);
preStmt.setTimestamp(7, new Timestamp(timeStamp));
preStmt.executeUpdate();
preStmt.close();
//con.close();
}
public static long getTimeStamp(){
long t = System.currentTimeMillis();
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//String timestamp = sdf.format(t);
return t; //timestamp;
}
}
I found the solution for my problem: it works very fast :)
package io;
import db.PostgresConnector;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
public class DbLogger3 {
public static void main (String args[]) throws Exception {
try {
Connection conn = new PostgresConnector().getConnection();
CopyManager copyManager = new CopyManager((BaseConnection) conn);
String str = new String();
//add 5000 data sets: (important: \r\n after each record to set a line feed (postgres interpretes that as the end of each dataset)
for (int i=0; i<5000; i++){
str += "2;100;99;6.00;12.00;11.00;13;28.06.2016 00:08;28.06.2016 00:08"+"\r\n";
}
//transform the String into bytes:
byte[] bytes = str.getBytes();
//create ByteArrayInputStream object
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
//insert into the database table (in my case: public.graph_data)
copyManager.copyIn("COPY public.graph_data FROM STDIN WITH DELIMITER ';'", input);
} catch (SQLException | IOException e) {
throw new Exception(e);
}
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
package Simple;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import com.sun.org.apache.xerces.internal.impl.xpath.regex.ParseException;
import java.util.LinkedList;
public class CheckJdbc {
private static final String DB_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_CONNECTION = "jdbc:mysql://localhost:3306/db";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "root";
private static int RECORD_COUNT = 1;
int days=1;
static int total=1;
public static java.util.LinkedList searchBetweenDates(java.util.Date startDate, java.util.Date endDate) {
java.util.Date begin = new Date(startDate.getTime());
java.util.LinkedList list = new java.util.LinkedList();
list.add(new Date(begin.getTime()));
java.util.Date end = new Date(endDate.getTime());
endDate.setTime(endDate.getTime() + 24*3600*1000);
while(begin.compareTo(endDate)<0){
list.add(new Date(begin.getTime()));
Timestamp timestamp = new Timestamp(new Date().getTime());
int total=1;
Calendar cal = Calendar.getInstance();
cal.setTime(startDate);
for(int d=0; d<=total; d++)
{
cal.add(Calendar.MINUTE, 2);
timestamp = new Timestamp(cal.getTime().getTime());
String S = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(timestamp);
String[] parts = S.split(" ");
// System.out.println("Date:" + parts[0]);
// System.out.println("Time:" + parts[1]);
String date=parts[0];
String time=parts[1];
begin = new Date(begin.getTime() + 86400000);
cal.setTime(endDate);
System.out.println(timestamp);
List<String> records = new ArrayList<String>();
StringBuffer record = new StringBuffer();
for (int i = 1; i <= RECORD_COUNT; i++) {
records = new ArrayList<String>(RECORD_COUNT);
int RECORD_COUNT= total;
for (int j = 0; j < total; j++) {
int a2 = 220 + j % 30; // 230 - 244 by 1
String wString = Integer.toString(a2);
String a = String.valueOf(a2);
double b2 = 0.12 + j % 3.9 * 0.01 ; // 1.3 - 3.9 by 0.1
String aString = Double.toString(a2);
String b = String.valueOf(b2);
b = b.substring(0, Math.min(b.length(), 5));
double c2 = 0.01 + j % 49 * 0.01 ; // 0.01 - 0.49 by 0.01
String bString = Double.toString(c2);
String c = String.valueOf(c2);
c = c.substring(0, Math.min(c.length(), 5));
record.append(a + "," + b + "," + c + "," +date+ ","+ time );
record.append("\t\t");
record.append("\n");
records.add(record.toString());
try {
String insertTableSQL = "INSERT INTO cmd1"
+ "(a, b, c ,date, time) " + "VALUES"
+ "("+record.toString()+")";
System.out.println("insertTableSQL - " + insertTableSQL);
insertRecordIntodb();
Connection dbConnection = null;
Statement statement = null;
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
statement.executeUpdate(insertTableSQL);
System.out.println(insertTableSQL);
System.out.println("Record is inserted into Db table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
}
}
}
}
}
return list;
}
#SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
//searchBetweenDates(d);
java.util.LinkedList hitList = searchBetweenDates(
new java.text.SimpleDateFormat("MM/dd/yyyy").parse("01/10/2016"),
new java.text.SimpleDateFormat("MM/dd/yyyy").parse("01/15/2016"));
String[] combo = new String[hitList.size()];
for(int i=0; i<hitList.size(); i++)
combo[i] = new java.text.SimpleDateFormat("MM/dd/yyyy").format(((java.util.Date)hitList.get(i)));
}
private static void insertRecordIntodb() {
}
private static Connection getDBConnection() {
Connection dbConnection = null;
try {
Class.forName(DB_DRIVER);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
try {
dbConnection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
return dbConnection;
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return dbConnection;
}
}
I want to call data for date and time which is in searchBetweenDates method into main method. I have created object in main method but still its not fetching. What should i do for that? As its not fetching data from date and time.
I am getting following error:
insertTableSQL - INSERT INTO cmd1(a, b, c ,date, time) VALUES(220,0.12,0.01,01/10/2016,00:02:00
)
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':02:00
)' at line 1
First of all, your code is not even valid Java code (i.e. it does not even compile). Secondly, you are calling a static method through an instance, which you shouldn't. Use:
Test.searchBetweenDates(startDate, endDate);
This, however won't make your code work per se, because startDate and endDate is null.
Check your main method:
public static void main(String[] args) throws Exception {
new Test().searchBetweenDates(startDate, endDate);
searchBetweenDates(startDate, endDate);
the parenthesis is missing. It should be:
public static void main(String[] args) throws Exception {
new Test().searchBetweenDates(startDate, endDate);
searchBetweenDates(startDate, endDate);
}
import java.io.*;
import java.sql.*;
public class CsvF {
public static void main(String[] args) {
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn= DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:xe","system","sandp");
conn.setAutoCommit(false);
Statement st=conn.createStatement();
ResultSet rs=st.executeQuery("select * from tet where to_char(S_DATE,'HH24') = '23'");
ResultSetMetaData rsmd = rs.getMetaData();
FileWriter cname = new FileWriter("D:\\asd.csv");
BufferedWriter bwOutFile = new BufferedWriter(cname);
StringBuffer sbOutput = new StringBuffer();
sbOutput.append("S_DATE");
bwOutFile.append(sbOutput);
bwOutFile.append(System.getProperty("line.separator"));
System.out.println("No of columns in the table:"+ rsmd.getColumnCount());
for (int i = 1; i <= rsmd.getColumnCount(); i++)
{
String fname = rsmd.getColumnName(i);
}
System.out.println();
while(rs.next())
{
System.out.print(rs.getString(1));
bwOutFile.append(rs.getString(1));
bwOutFile.append(System.getProperty("line.separator"));
bwOutFile.flush();
System.out.println();
}
conn.close();
}
catch(SQLException se)
{
se.printStackTrace();
}
catch(Exception e)
{
System.out.println("Unable to connect to database" +e);
}
}
}
here i am getting data into asd.csv file as follows=
2015-2-26.23.21. 0. 0
2015-2-26.23.43. 0. 0
2015-2-27.23.28. 0. 0
2015-2-27.23.50. 0. 0
2015-3-1.23.19. 0. 0
2015-3-1.23.41. 0. 0
but i want to get data as following format =
2015-02-26 23:21
2015-02-26 23:43
2015-02-27 23:28
2015-02-27 23:50
2015-03-01 23:19
2015-03-01 23:41
i am getting an extra dot(".") in the output... what i am doing wrong?
i have create a table named tet with coloumn(S_DATE) where S_DATE is timestamp...can anyone help me?
Use rs.getTimestamp() instead of rs.getString() and convert your timestamp to string using SimpleDateFormat.
TimeStamp ts= rs.getTimeStamp(1);
SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd hh:mm");
String yourFormatedDate = formater.format(ts);
just curious if anyone has any idea for making this program more simple. It reads records from a database into an ArrayList and allows the user to search for records by state. It processes a database of 1 million records in aprox 16000ms.
import java.sql.*;
import java.util.*;
public class ShowEmployeeDB
{
public static void main(String args[])
{
ArrayList <String> Recs = new ArrayList <String>();
String driverName = "sun.jdbc.odbc.JdbcOdbcDriver";
String connectionURL = "jdbc:odbc:CitizensDB";
Connection con = null;
Statement stmt = null;
String sqlStatement = "SELECT * FROM Citizens";
ResultSet rs = null;
int r = 0;
Scanner scan = new Scanner(System.in);
String search = null;
long starttime = System.currentTimeMillis();
try
{
Class.forName(driverName).newInstance();
con = DriverManager.getConnection(connectionURL);
stmt = con.createStatement();
rs = stmt.executeQuery(sqlStatement);
String ID = null;
String Age = null;
String State = null;
String Gender = null;
String Status = null;
String record = null;
while (rs.next())
{
for (int k = 1; k <= 1; ++k)
{
ID = rs.getString(k) + " ";
for (int j = 2; j <= 2; ++j)
Age = rs.getString(j) + " ";
for (int i = 3; i <= 3; ++i)
State = rs.getString(i).toUpperCase() + " ";
for (int h = 4; h <= 4; ++h)
Gender = rs.getString(h) + " ";
for (int g = 5; g <= 5; ++g)
Status = rs.getString(g) + " ";
}//for
record = ID + Age + State + Gender + Status;
Recs.add(record);
++r;
}//while
rs.close();
stmt.close();
con.close();
} catch (Exception ex) { ex.printStackTrace(); }
String endtime = System.currentTimeMillis() - starttime + "ms";
System.out.println(endtime);
System.out.print("Enter A Search State: ");
search = scan.nextLine().toUpperCase();
Iterator<String> iter = Recs.iterator();
while(iter.hasNext())
{
String s = iter.next();
if (s.contains(search))
{
System.out.println(s);
}
}//while
} // main
} // ShowEmployeeBD
Any advice would be greatly appreciated. Thank you in advance!
If search is not often, I would suggest to take the search string input before running the query, so that search results are directly from the DB. I this case you do not have to reiterate all 1 million records.
Perform searching directly on DB rather than fetching all the records and searching through java code.
Also if search is on multiple column, then prepare a meta data in DB at a single place on the basis of IDs, and the meta data can further be used for fetching the required results that match the query.
Separate your logic from the technical stuff. In such a convolut it is difficult to run unit tests or any optimizations.
Why do you need for loops, when only asking one value.
Use StringBuilder instead of String concatenation.
Use either try-with or put your close statements in a finally clause.
Don't initialize variables you don't need (r).
Use for each statements.
Query the database, not the result set.
Tune your database.
If you are only searching for a state, filter only those, so build an object and compare the state instead of a string contains.
Compare the state before storing strings in the list.
Tune your list because it constantly grows with 1Mio records.
Use a hashset instead of an arraylist.
Develop against interfaces.
A better program might look like following:
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class ShowEmployeeDB {
private static final String DRIVERNAME = "sun.jdbc.odbc.JdbcOdbcDriver";
private static final String CONNECTIONURL = "jdbc:odbc:CitizensDB";
private static final String SELECT_CITIZENS = "SELECT * FROM Citizens";
static {
try {
DriverManager.registerDriver((Driver) Class.forName(DRIVERNAME).newInstance());
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
public static void main(final String args[]) {
System.out.print("Enter A Search State: ");
searchRecords();
}
private static void searchRecords() {
try(Scanner scan = new Scanner(System.in);) {
final String state = scan.nextLine();
final long starttime = System.currentTimeMillis();
final Set<Record> records = searchRecordsByState(state);
System.out.println(System.currentTimeMillis() - starttime + "ms");
for(final Record r : records) {
System.out.println(r);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static Set<Record> searchRecordsByState(final String stateToFilter) {
final Set<Record> records = new HashSet<>();
try(Connection con = DriverManager.getConnection(CONNECTIONURL);
PreparedStatement stmt = con.prepareStatement(SELECT_CITIZENS);
ResultSet rs = stmt.executeQuery(); ) {
while(rs.next()) {
final String state = rs.getString(3);
if(state.equalsIgnoreCase(stateToFilter)) {
final Record r = new Record(rs.getString(1), rs.getString(2), state, rs.getString(4), rs.getString(5));
records.add(r);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return records;
}
}
class Record {
String id, age, state, gender, status;
public Record(String id, String age, String state, String gender, String status) {
this.id = id;
this.age = age;
this.state = state;
this.gender = gender;
this.status = status;
}
public String getState() {
return state;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(id).append(' ')
.append(age).append(' ')
.append(state).append(' ')
.append(gender).append(' ')
.append(status);
return sb.toString();
}
}
This is untested, because I don't have a database with a million entries by hand.
But the best would be to query the database and catch only those entries you need. So use the WHERE-clause in your statement.
I'm attempting to fix a plugin I wrote a long time ago for Craftbukkit, but I'm stumped on one section. I've searched Google with little luck, and I've asked other Java developers only to hear that I shouldn't be using a for loop because it's rather basic, or that I'm using a boolean expression in the wrong place. Nobody will tell me how I can fix this, so I'll know for future references - Below is the class that throws the error:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.logging.Logger;
import org.bukkit.configuration.file.FileConfiguration;
public class Database
{
private static String host = null;
private static String port = null;
private static String database = null;
private static String table = null;
private static String username = null;
private static String password = null;
private static String colUsername = null;
private static Logger logger = null;
public static void init(FileConfiguration config, Logger log)
{
logger = log;
host = config.getString("DBHost");
port = config.getString("DBPort");
database = config.getString("DBName");
table = config.getString("DBTable");
username = config.getString("DBUser");
password = config.getString("DBPass");
colUsername = config.getString("ColUsername");
}
public static Hashtable<String, Object> getUserInfo(String user)
{
String url = "jdbc:mysql://" + host + ":" + port + "/" + database;
String query = "SELECT * FROM " + table + " WHERE " + colUsername + " = ?";
Connection connect = null;
PreparedStatement stmt = null;
ResultSet result = null;
Hashtable<String, Object> userInfo = new Hashtable<String, Object>();
try
{
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection(url, username, password);
stmt = connect.prepareStatement(query);
stmt.setString(1, user);
result = stmt.executeQuery();
ResultSetMetaData rsmd;
int i;
for (; result.next(); i <= rsmd.getColumnCount())
{
rsmd = result.getMetaData();
i = 1; continue;
userInfo.put(rsmd.getColumnName(i), result.getObject(i));i++;
}
return userInfo;
}
catch (ClassNotFoundException e)
{
logger.warning("Unable to load driver. Using default behaviour.");
e.printStackTrace();
}
catch (SQLException e)
{
logger.warning("Database error. Using default behaviour.");
e.printStackTrace();
}
finally
{
if (result != null) {
try
{
result.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
if (stmt != null) {
try
{
stmt.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
if (connect != null) {
try
{
connect.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
return null;
}
}
The error I encounter is in this part of the code:
for (; result.next(); i <= rsmd.getColumnCount())
{
rsmd = result.getMetaData();
i = 1; continue;
userInfo.put(rsmd.getColumnName(i), result.getObject(i));i++;
}
Where I get the error "Syntax error on token "<=", invalid AssignmentOperator"
How should I go about fixing this, and how can I improve it?
EDIT #1:
This is my updated code, according to Jon's answer:
try
{
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection(url, username, password);
stmt = connect.prepareStatement(query);
stmt.setString(1, user);
result = stmt.executeQuery();
ResultSetMetaData rsmd = result.getMetaData();
while (result.next()) {
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
rsmd = result.getMetaData();
userInfo.put(rsmd.getColumnName(i), result.getObject(i));i++;
}
}
return userInfo;
}
Basically this is the wrong way round:
for (; result.next(); i <= rsmd.getColumnCount())
It should possibly be:
for (; i <= rsmd.getColumnCount(); result.next())
Although more likely, you actually want:
while (result.next()) {
// This outer loop is executed once per row
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
// This inner loop is executed once per column (per row, as it's
// within the outer loop)
}
}
Having said that, you're not even initializing rsmd, which doesn't help. I suspect you may want to call ResultSet.getMetadata(), e.g.
rsmd = result.getMetadata();
For reference, the three parts of the for statement declaration are as follows:
The first part (empty in your case) is performed once, as initialization
The second part is a condition to check on each iteration; the loop ends when the condition evaluates to false
The third part is a statement is a step to take at the end of each iteration
See section 14.14.1 of the JLS or the for statement part of the Java tutorial for more details.
This won't work in the last part of a for loop:
i <= rsmd.getColumnCount()
Perhaps you meant this?
for (; i <= rsmd.getColumnCount(); result.next())
Basic syntax of a for-loop:
for (any; boolean; any)
your's is
for (any; any; boolean)
Just change the order.