I'm trying to work through creating a very simple class to send queries to an instance of Oracle XE 11g, essentially making a very simple SQL*Plus to get the basics of JDBC down.
The source code I'm currently working with is:
public class Example {
static String username, password;
static String dbDriver = "oracle.jdbc.driver.OracleDriver";
static String dbConnection = "jdbc:oracle:thin:#//localhost:1521/xe";
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String line;
Connection c = null;
Statement stmt = null;
int loginAttempts = 0;
// Log in loop
do {
try {
Class.forName(dbDriver);
System.out.print("Enter username: ");
line = input.nextLine();
if (line.contains("/")) {
String[] login = line.split("/");
if (login.length != 2) {
System.out
.println("Unrecognized information, exiting...");
System.exit(0);
}
username = login[0].trim();
password = login[1].trim();
} else {
username = line;
System.out.print("Enter password: ");
password = input.nextLine();
}
c = DriverManager.getConnection(dbConnection, username,
password);
stmt = c.createStatement();
loginAttempts = -1;
} catch (ClassNotFoundException e) {
System.err.println("Unable to connect to database, exiting...");
System.exit(-1);
} catch (SQLException e) {
System.out.println("Username and/or password is incorrect");
if (++loginAttempts == 1) {
System.out.println("Too many failed login attempts, exiting...");
System.exit(0);
}
}
} while (loginAttempts != -1);
// Input loop
for (;;) {
try {
// Write out the prompt text and wait for input
if(c == null) {
throw new IllegalStateException("Connection should not be null");
}
System.out.print(c.getSchema() + ":> ");
String tmp = input.nextLine();
// Check if the user entered "exit"
if (tmp.toLowerCase().equals("exit")) {
System.out.println("Exiting...");
input.close();
System.exit(0);
}
String query;
// TODO: For some reason, no semi-colon is allowed
if (tmp.charAt(tmp.length() - 1) == ';')
query = tmp.split(";")[0];
else
query = tmp;
// System.out.println(query);
ResultSet rset = stmt.executeQuery(query);
ResultSetMetaData rmd = rset.getMetaData();
int colCount = rmd.getColumnCount();
// Column indices start with 1, print column names
for (int i = 1; i <= colCount; i++) {
System.out.printf("%-20.20s ", rmd.getColumnName(i));
}
System.out.println();
while (rset.next()) {
for (int i = 0; i < colCount; i++) {
System.out.printf("%-20.20s | ", rset.getString(i + 1));
}
System.out.println();
}
System.out.println();
} catch (SQLSyntaxErrorException e) {
System.out.println("Encountered a syntax error:\n"
+ e.getMessage());
} catch (SQLException e) {
System.err.println("An unexpected error occurred");
e.printStackTrace();
input.close();
System.exit(-1);
}
}
}
}
In the second try/catch block, in the for(;;) loop, I get the following output:
Enter username: hr/hr
Exception in thread "main" java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.getSchema()Ljava/lang/String;
at jdbctest.Example.main(Example.java:69)
I checked out the Oracle docs (java.lang.AbstractMethodError), and it says that this error can only be thrown if:
"the definition of some class has incompatibly changed since the currently executing method was last compiled."
I'm thinking that there's something I'm missing with line 27, but I'm not sure how to approach this problem and any guidance would be extremely helpful.
I believe that your problem is due to the fact that you use a JDBC driver for a version of Java <= 6 and you use Java 7 or higher because the method Connection#getSchema() has been added in Java 7.
Use the latest version of your JDBC driver to avoid such issue or at least a JDBC driver compatible with your version of Java.
This works on DB2 (and an old version of the driver)
Connection.getMetaData().getConnection().getSchema();
I am trying to pass in a JTable object which has columns DiscountID and Name. I am basically trying to get a row of the first column which is selected in JTable A (a DiscountID) and upon this set data relating to this selected record in JTable B which is JTable5 in the rs.next() loop.
The problem I have now is that since initially int row = table.getSelectedRow(); I'm having to set it to 0 to avoid an IndexOutOfBoundsException but then when I run the program JTable B will show information correlating to the first record in JTable A without any selection of data by me. I don't want any information to be displayed at all in JTable B until I select a record from JTable A whilst also avoiding the IndexOutOfBoundsException. It will be much appreciated if anyone can help me to fix this I've been trying hard to find a solution.
Here is the code to my method:
public static ArrayList<FlexiBand> getFlexiBands(JTable table, JTable table2) {
ArrayList<FlexiBand> flexiband = new ArrayList<FlexiBand>();
try {
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
con = DriverManager
.getConnection("jdbc:mysql://localhost:3306/abpp034?user=abpp034&password=120001772");
stmt = con
.prepareStatement("SELECT UpperBound, PercentageRate FROM FlexiBand WHERE DiscountID = ?");
int row = table.getSelectedRow();
if (row == -1) {
row = 0;
for (int x = 0; x < table2.getRowCount(); x++) {
table2.setValueAt("", x, 0);
table2.setValueAt("", x, 1);
}
}
System.out.println(row); // This is printing me 0 meaning that row is still 0
System.out.println(table.getValueAt(row, 0)); // This means that row will be equal to 0
// when it goes to the next line.
stmt.setObject(1, table.getValueAt(row, 0));
try {
rs = stmt.executeQuery();
int i = 0;
while (rs.next()) {
FlexiBand fb = new FlexiBand();
fb.setUpperBound(rs.getInt("UpperBound"));
fb.setPercentageRate(rs.getInt("PercentageRate"));
flexiband.add(fb);
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException se) {
System.out.println(se.getErrorCode());
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException se) {
System.out.println(se.getErrorCode());
}
}
if (con != null) {
try {
con.close();
} catch (SQLException se) {
System.out.println(se.getErrorCode());
}
}
}
} catch (SQLException ex) {
Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
}
return flexiband;
}
Here is where I call the method:
public static void main(String[] args) {
DiscountGUIView dgv = new DiscountGUIView();
setDiscountNames("Fixed", dgv.getjComboBox2());
getFlexiBands(dgv.getjTable2(), dgv.getjTable5());
}
in the same class as the method.
Just do in this way. Check whether row is selected or not.
public static void main(String[] args) {
DiscountGUIView dgv = new DiscountGUIView();
setDiscountNames("Fixed", dgv.getjComboBox2());
ArrayList<FlexiBand> flexiband = null;
if (dgv.getjTable2().getSelectedRow != -1) {
flexiband = getFlexiBands(dgv.getjTable2(), dgv.getjTable5());
}
if (flexiband !=null) {
// user selected a row, do what ever you want to do
} else {
// nothing is selected
// skip other operations
}
}
I have a sql query to select data integer
I want do a test about this data that I test data in column with number 10
If I have 10 in column so pass to 10--
I do loop for into while
The result is correct but it's repeated many times
This is my code
int vl=10;
boolean found = false;
try {
if (jComboBox6.getSelectedIndex()>-1){
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+getdb(), "", "");
stmt = conn.createStatement();
ResultSet res=stmt.executeQuery( "SELECT VLAN FROM tt ");
while(res.next()) {
for(vl=10;vl>1;vl--) {
if(Integer.parseInt(res.getString(1))==vl) {
System.out.print(vl);
found = true;
break;
}
if (!found) {
System.out.print("NO");
//found = false;
break;
}
}
}
res.close();
}
conn.close();
} catch (SQLException ex) {
Logger.getLogger(Etat_lieu.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.print("NO")
this line will be printed every time there is no match in the for loop.
Update
Let's simplify the problem.
boolean found = false;
while(res.next()) {
int value = Integer.parseInt(res.getString(1));
if (value == 10) {
System.out.print(value);
found = true;
}
[..do something else..]
}
if(!found) {
System.out.print("NO");
}
I think it's not worth to put an inner loop for a simple range check.
Im looking to create a for loop for R[X]
X is stated in a previous for loop
The syntax for a for loop isnt giving me any help to this at all.
r is a short for route, say it picks R1 that would correspond to a row in a database
so X can be 1,2,3 etc..
So is it possible to say For(R[X])?
CODE:
for(int X = 1; X < records; X++) {
for(r[X]) {
//<editor-fold defaultstate="collapsed" desc="To check if RX is in Collision Table">
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
//load the oracle driver...needs to be in classes folder in jre folder
} catch (ClassNotFoundException e) {
System.out.println(
" Can't find class oracle.jdbc.driver.OracleDriver");
System.exit(1);
}
Connection conn5 = null;
//new connection object
Statement stmtFindRx = null;
//new statemnt object
ResultSet checkRx = null;
//new record set object
try {
conn5 = DriverManager.getConnection("jdbc:oracle:thin:#oracle.staff.ittralee.ie:1521:orcl",
"*", "*");
stmtFindRx = conn5.createStatement();
// create the statement for this connection
//</editor-fold>
checkRx = stmtFindRx.executeQuery(
"*********");
// get the results of select query and store in recordset object
while (checkRx.next()) {
// move to first/next record of recordset
JOptionPane.showMessageDialog(null, " the answer is " + checkRx.getString(1));
//JOptionPane.showMessageDialog(null, " the answer is " + fRoutes);
// output next record using string format
}
//<editor-fold defaultstate="collapsed" desc="Error handling for Select Statement">
checkRx.close();
checkRx = null;
stmtFindRx.close();
stmtFindRx = null;
conn5.close();
conn5 = null;
} catch (SQLException e) {
System.out.println(" A SQL error: " + e.getMessage());
} finally {
if (checkRx != null) {
try {
checkRx.close();
} catch (SQLException ignore) {
}
}
if (stmtFindRx != null) {
try {
stmtFindRx.close();
} catch (SQLException ignore) {
}
}
if (conn5 != null) {
try {
conn5.close();
} catch (SQLException ignore) {
}
}
}
// </editor-fold>
}
}
Taking a guess at a possible answer to the question i think you're trying to ask ...
Assuming that R[X] will give you some sort of collection, perhaps you might be looking for:
foreach (Route route in R[X]) {
I'm trying to import all googlebooks-1gram files into a postgresql database. I wrote the following Java code for that:
public class ToPostgres {
public static void main(String[] args) throws Exception {
String filePath = "./";
List<String> files = new ArrayList<String>();
for (int i =0; i < 10; i++) {
files.add(filePath+"googlebooks-eng-all-1gram-20090715-"+i+".csv");
}
Connection c = null;
try {
c = DriverManager.getConnection("jdbc:postgresql://localhost/googlebooks",
"postgres", "xxxxxx");
} catch (SQLException e) {
e.printStackTrace();
}
if (c != null) {
try {
PreparedStatement wordInsert = c.prepareStatement(
"INSERT INTO words (word) VALUES (?)", Statement.RETURN_GENERATED_KEYS
);
PreparedStatement countInsert = c.prepareStatement(
"INSERT INTO wordcounts (word_id, \"year\", total_count, total_pages, total_books) " +
"VALUES (?,?,?,?,?)"
);
String lastWord = "";
Long lastId = -1L;
for (String filename: files) {
BufferedReader input = new BufferedReader(new FileReader(new File(filename)));
String line = "";
while ((line = input.readLine()) != null) {
String[] data = line.split("\t");
Long id = -1L;
if (lastWord.equals(data[0])) {
id = lastId;
} else {
wordInsert.setString(1, data[0]);
wordInsert.executeUpdate();
ResultSet resultSet = wordInsert.getGeneratedKeys();
if (resultSet != null && resultSet.next())
{
id = resultSet.getLong(1);
}
}
countInsert.setLong(1, id);
countInsert.setInt(2, Integer.parseInt(data[1]));
countInsert.setInt(3, Integer.parseInt(data[2]));
countInsert.setInt(4, Integer.parseInt(data[3]));
countInsert.setInt(5, Integer.parseInt(data[4]));
countInsert.executeUpdate();
lastWord = data[0];
lastId = id;
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
However, when running this for ~3 hours it only placed 1.000.000 entries in the wordcounts table. When I check the amount of lines in the entire 1gram dataset it's 500.000.000 lines. So to import everything would take about 62.5 days, I can accept that it imports in about a week, but 2 months? I think I'm doing something seriously wrong here(I do have a server that runs 24/7, so I can actually run it for this long, but faster would be nice XD)
EDIT: This code is how I solved it:
public class ToPostgres {
public static void main(String[] args) throws Exception {
String filePath = "./";
List<String> files = new ArrayList<String>();
for (int i =0; i < 10; i++) {
files.add(filePath+"googlebooks-eng-all-1gram-20090715-"+i+".csv");
}
Connection c = null;
try {
c = DriverManager.getConnection("jdbc:postgresql://localhost/googlebooks",
"postgres", "xxxxxx");
} catch (SQLException e) {
e.printStackTrace();
}
if (c != null) {
c.setAutoCommit(false);
try {
PreparedStatement wordInsert = c.prepareStatement(
"INSERT INTO words (id, word) VALUES (?,?)"
);
PreparedStatement countInsert = c.prepareStatement(
"INSERT INTO wordcounts (word_id, \"year\", total_count, total_pages, total_books) " +
"VALUES (?,?,?,?,?)"
);
String lastWord = "";
Long id = 0L;
for (String filename: files) {
BufferedReader input = new BufferedReader(new FileReader(new File(filename)));
String line = "";
int i = 0;
while ((line = input.readLine()) != null) {
String[] data = line.split("\t");
if (!lastWord.equals(data[0])) {
id++;
wordInsert.setLong(1, id);
wordInsert.setString(2, data[0]);
wordInsert.executeUpdate();
}
countInsert.setLong(1, id);
countInsert.setInt(2, Integer.parseInt(data[1]));
countInsert.setInt(3, Integer.parseInt(data[2]));
countInsert.setInt(4, Integer.parseInt(data[3]));
countInsert.setInt(5, Integer.parseInt(data[4]));
countInsert.executeUpdate();
lastWord = data[0];
if (i % 10000 == 0) {
c.commit();
}
if (i % 100000 == 0) {
System.out.println(i+" mark file "+filename);
}
i++;
}
c.commit();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
I reached 1.5 million rows in about 15 minutes now. That's fast enough for me, thanks all!
JDBC connections have autocommit enabled by default, which carries a per-statement overhead. Try disabling it:
c.setAutoCommit(false)
then commit in batches, something along the lines of:
long ops = 0;
for(String filename : files) {
// ...
while ((line = input.readLine()) != null) {
// insert some stuff...
ops ++;
if(ops % 1000 == 0) {
c.commit();
}
}
}
c.commit();
If your table has indexes, it might be faster to delete them, insert the data, and recreate the indexes later.
Setting autocommit off, and doing a manual commit every 10 000 records or so (look into the documentation for a reasonable value - there is some limit) could speed up as well.
Generating the index/foreign key yourself, and keeping track of it should be faster than wordInsert.getGeneratedKeys(); but I'm not sure, whether it is possible from your content.
There is an approach called 'bulk insert'. I don't remember the details, but its a starting point for a search.
Write it to do threading, running 4 threads at the same time, or split it up in sections (read from config file) and distribute it to X machines and have them get the data togeather.
Use batch statements to execute multiple inserts at the same time, rather than one INSERT at a time.
In addition I would remove the part of your algorithm which updates the word count after each insert into the words table, instead just calculate all of the word counts once inserting the words is complete.
Another approach would be to do bulk inserts rather than single inserts. See this question Whats the fastest way to do a bulk insert into Postgres? for more information.
Create threads
String lastWord = "";
Long lastId = -1L;
PreparedStatement wordInsert;
PreparedStatement countInsert ;
public class ToPostgres {
public void main(String[] args) throws Exception {
String filePath = "./";
List<String> files = new ArrayList<String>();
for (int i =0; i < 10; i++) {
files.add(filePath+"googlebooks-eng-all-1gram-20090715-"+i+".csv");
}
Connection c = null;
try {
c = DriverManager.getConnection("jdbc:postgresql://localhost/googlebooks",
"postgres", "xxxxxx");
} catch (SQLException e) {
e.printStackTrace();
}
if (c != null) {
try {
wordInsert = c.prepareStatement(
"INSERT INTO words (word) VALUES (?)", Statement.RETURN_GENERATED_KEYS
);
countInsert = c.prepareStatement(
"INSERT INTO wordcounts (word_id, \"year\", total_count, total_pages, total_books) " +
"VALUES (?,?,?,?,?)"
);
for (String filename: files) {
new MyThread(filename). start();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
class MyThread extends Thread{
String file;
public MyThread(String file) {
this.file = file;
}
#Override
public void run() {
try {
super.run();
BufferedReader input = new BufferedReader(new FileReader(new File(file)));
String line = "";
while ((line = input.readLine()) != null) {
String[] data = line.split("\t");
Long id = -1L;
if (lastWord.equals(data[0])) {
id = lastId;
} else {
wordInsert.setString(1, data[0]);
wordInsert.executeUpdate();
ResultSet resultSet = wordInsert.getGeneratedKeys();
if (resultSet != null && resultSet.next())
{
id = resultSet.getLong(1);
}
}
countInsert.setLong(1, id);
countInsert.setInt(2, Integer.parseInt(data[1]));
countInsert.setInt(3, Integer.parseInt(data[2]));
countInsert.setInt(4, Integer.parseInt(data[3]));
countInsert.setInt(5, Integer.parseInt(data[4]));
countInsert.executeUpdate();
lastWord = data[0];
lastId = id;
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}