JDBC - loosen coupling - java

We are currently having a school project where our application takes input from a file with a certain format, creates a table in MySQL and fills it with data. While coding this I noticed I use a lot of dependencies, which I have earlier read is a bad habit to get into. Reducing coupling has not really been a big topic yet. Searching around, I found most answers were about interfaces. I don't think they were clear enough answers for me, nor did it seem beneficial without repeating methods.
How can I loosen the coupling in my code? Any good general tips and tricks?
PS: void showTable and stringBuilderShowTable are not implemented, nor working.
public class DBService {
DBConnection dbc;
Connection con;
//Statement stmt;
public DBService()
{
dbc = new DBConnection();
con = dbc.getConnection();
}
public void copyFile(String fileName, String tableName) throws SQLException {
DataManager dm = new DataManager();
dm.sortData(fileName);
createTable(fileName, tableName, con);
insertData(fileName, tableName, con);
}
public void showTable (String tableName)
{
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery
("SELECT * FROM " + tableName);
System.out.println("id name job");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String job = rs.getString("job");
System.out.println(id+" "+name+" "+job);
}
}
catch(SQLException e){
System.out.println("SQL exception occured" + e);
}
}
public void createTable(String fileName, String tableName, Connection con) throws SQLException {
try (Statement stmt2 = (Statement) con.createStatement())
{
String query1 = stringBuilderMeta(fileName, tableName);
stmt2.execute(query1);
if (stmt2.getWarnings() == null)
{
System.out.println("\n### Table " + tableName + " is created");
} else
{
System.out.println("### " + stmt2.getWarnings());
}
stmt2.close();
}
}
public void insertData(String fileName, String tableName, Connection con) throws SQLException
{
try (Statement stmt = (Statement) con.createStatement())
{
String query1 = stringBuilderData(fileName, tableName);
stmt.execute(query1);
if (stmt.getWarnings() == null)
{
System.out.println("\n### Table " + tableName + " has been successfully filled");
} else
{
System.out.println("### " + stmt.getWarnings());
}
stmt.close();
}
}
public String stringBuilderMeta(String fileName, String tableName)
{
DataManager dm = new DataManager();
dm.sortData(fileName);
StringBuilder builder = new StringBuilder();
builder.append("" + "Create table ").append(tableName).append(" (\n");
for (int i = 0; i < dm.fileMetaData.size();i++) {
DataFromFile d = (DataFromFile)dm.fileMetaData.get(i);
String test = d.getName();
String test2 = d.getDatatype();
String test3 = d.getLimit();
if(i < (dm.fileMetaData.size()-1))
{
builder.append(test).append(" ").append(test2).append(" (").append(test3).append("),\n");
}
else{
builder.append(test).append(" ").append(test2).append(" (").append(test3).append(")\n");
}
}
builder.append(");");
String string = builder.toString();
return string;
}
public String stringBuilderShowTable(String fileName, String tableName)
{
DataManager dm = new DataManager();
dm.sortData(fileName);
StringBuilder builder = new StringBuilder();
//builder.append("" + "SELECT * FROM " + tableName + ""
for (int i = 0; i < dm.fileMetaData.size();i++) {
DataFromFile d = (DataFromFile)dm.fileMetaData.get(i);
String test = d.getName();
String test2 = d.getDatatype();
String test3 = d.getLimit();
if(i < (dm.fileMetaData.size()-1))
{
builder.append(test).append(" ").append(test2).append(" (").append(test3).append("),\n");
}
else{
builder.append(test).append(" ").append(test2).append(" (").append(test3).append(")\n");
}
}
builder.append(");");
String string = builder.toString();
System.out.print(string);
return string;
}
public String stringBuilderData(String fileName, String tableName)
{
DataManager dm = new DataManager();
dm.sortData(fileName);
int counter = 0;
int counter2 = dm.reader.wordsPerLine;
StringBuilder builder = new StringBuilder();
for(int j = 0; j < dm.boo; j++)
{
builder.append("" + "INSERT INTO ").append(tableName).append (" (");
for (int i = 0; i < dm.fileMetaData.size(); i++) {
DataFromFile d = (DataFromFile) dm.fileMetaData.get(i);
if (i < (dm.fileMetaData.size() - 1)) {
builder.append(d.getName()).append(", ");
} else {
builder.append(d.getName());
}
}
builder.append(")\n").append("VALUES (");
for (int i = counter; i < counter2; i++) {
if (i < (counter2 - 1)) {
builder.append("'" + dm.fileData.get(i) + "'" + ",");
} else {
builder.append("'" + dm.fileData.get(i) + "'");
}
counter++;
}
counter2 = counter2+dm.reader.wordsPerLine;
builder.append(");\n");
}
String string = builder.toString();
System.out.print(string);
return string;
}
}

It's a big question. A lot of what's gone into standard application architectures has to do with decoupling (and related, separation of concerns).
You may get some ideas from the traditional OO design patterns: https://en.wikipedia.org/wiki/Design_Patterns
Having collaborations of objects with defined roles (probably divided into architectural layers, and usually interacting through interfaces) is one technique. An application might have a presentation layer (further divided into an MVC structure) for showing things to the user, a data access layer for talking to the database, and a service layer in between... instead of one object doing all these things. A whole course could be devoted to the discipline of writing object that don't bleed across those types of architecture layers.
You also might want to look at "inversion of control" or "dependency injection". There are several frameworks for this, but the basic idea is only this: A class needs to use an object that implements the SomeDependencyINeed interface, but instead of directly saying myVariable = new ImplementationOfSomeDependencyINeed(); it provides a way that it can be given a SomeDependencyINeed reference (a constructor argument, or a setter method). A framework like Spring provides an "inversion of control container" (or IoC container) that normally provides ("injects") the dependency instances; or without a framework you might have some sort of builder or confgurer object with that responsibility.
The trouble is, a school project usually isn't big enough - and more importantly, usually isn't maintained for long enough - to show the benefit of these techniques. So as a student if you do them, you'll see all the cost - it takes longer to get up and running, sometimes you do things a specific way that might seem unnecessary - but you won't usually see the upside.

Related

Trying to read 700k+ of data and the Error "GC Overhead Limit Exceeded" occurred

Alright so I need help in reviewing my codes because I'm kinda still new in programming (currently in my second year of Diploma in Computer Science). I got this error as in the title GC Overhead Limit Exceeded when I tried running my code below.
A brief explanation of this code, I'm trying to read data from a CSV File and then transfer it to a database. FYI, there are actually 10 tables/CSV files that I need to read, but on this I'll show this one table Tickets because the error only occurred when I tried to read that table/file. The other tables have hundreds of rows/data only while the table Tickets have 735,504 of rows/data. Furthermore, I've succeeded in reading 450,028 of data after 6 hours of running the code before the error occurred.
What can I do to fix this error? What can be modified to improve my code? I really appreciate it if you guys can help me :)
public class Demo2 {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/database";
String username = "root";
String password = "password";
try {
//Connect to the database
Connection connection = DriverManager.getConnection(url, username, password);
//Test on one table only
String tableName = "Tickets";
System.out.println("Connecting to TABLE " +tableName +"...");
readCSVFile(tableName, connection);
System.out.println();
System.out.println("THE END");
connection.close();//close connection to the database
}
catch (SQLException e) {
System.out.println("ERROR at main(): SQLException!!");
e.printStackTrace();
}
}
static int countNewRow = 0;
static int countUpdatedRow = 0;
//Method to read the CSV File
static void readCSVFile(String tableName, Connection conn) {
//Read CSV File
try {
String path = tableName +".csv";
BufferedReader br = new BufferedReader(new FileReader(path));
br.readLine();//skip the first line
String inData;
//Read The Remaining Line
while((inData=br.readLine()) != null)
{
String[] rowData = inData.split(",");
ArrayList <String> rowDataList = new ArrayList<String>();
for (int i=0; i<rowData.length; i++)
rowDataList.add(rowData[i]);
//To combine String that starts and ends with "
for(int i=0; i<rowDataList.size(); i++) {
if (rowDataList.get(i).charAt(0) == '"') {
String string1 = rowDataList.get(i).substring(1, rowDataList.get(i).length());
String string2 = rowDataList.get(i+1).substring(0, rowDataList.get(i+1).length()-1);
String combined = string1 +"," +string2;
rowDataList.set(i, combined);
rowDataList.remove(i+1);
break;
}
}
//Remove the RM
for(int i=0; i<rowDataList.size(); i++) {
if (rowDataList.get(i).startsWith("RM")) {
String string = rowDataList.get(i).substring(2);
rowDataList.set(i, string);
}
}
//This is just to keep track of the data that has been read
System.out.println("[" +rowDataList.get(0) +"]");
//Transfer the data to the database
insertToDatabase(conn, tableName, rowDataList);
}
System.out.println("New Row Added : " +countNewRow);
System.out.println("Updated Row : " +countUpdatedRow);
System.out.println("== Process Completed ==");
br.close();
}
catch (FileNotFoundException e) {
System.out.println("ERROR at readCSVFile(): FileNotFoundException!!");
e.printStackTrace();
}
catch (IOException e) {
System.out.println("ERROR at readCSVFile(): IOException!!");
e.printStackTrace();
}
catch (SQLException e) {
System.out.println("ERROR at readCSVFile(): SQLException!!");
e.printStackTrace();
}
catch (ParseException e) {
System.out.println("ERROR at readCSVFile(): ParseException!!");
e.printStackTrace();
}
}
static void insertToDatabase(Connection connection, String tableName, ArrayList <String> rowDataList) throws SQLException, ParseException {
String tableIdName = tableName;
if (tableIdName.charAt(tableIdName.length()-1) == 's')
tableIdName = tableIdName.substring(0, tableIdName.length()-1);
//To read row
String rowID = rowDataList.get(0);
String selectSQL = "SELECT * FROM " +tableName +" "
+"WHERE " +tableIdName +"_ID = " +rowID;
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery(selectSQL);
boolean value = result.next();
//INSERT # UPDATE row
if (value == true) { //Update Row if the data is already existed
updateStatementt(tableName, connection, rowDataList);
countUpdatedRow++;
}
else { //Insert New Row
insertStatementt(tableName, connection, rowDataList);
countNewRow++;
}
}
//Method to insert data to the database
static void insertStatementt(String tableType, Connection conn, ArrayList <String> rowDataList) throws SQLException, ParseException {
//Generate Question Mark
String generateQuestionMark = null;
if(rowDataList.size() == 1)
generateQuestionMark = "?";
else
generateQuestionMark = "?, ";
for(int i=1; i<rowDataList.size(); i++) {
if(i!=rowDataList.size()-1)
generateQuestionMark += "?, ";
else
generateQuestionMark += "?";
}
//Insert sql
String sql = "INSERT INTO " +tableType +" VALUES (" +generateQuestionMark +")";
PreparedStatement insertStatement = conn.prepareStatement(sql);
//Insert data
//There are other 'if' and 'else if' statements here for other tables
else if (tableType.equals("Tickets")) {
int ticketID = Integer.parseInt(rowDataList.get(0));
int movieId = Integer.parseInt(rowDataList.get(1));
int theaterId = Integer.parseInt(rowDataList.get(2));
String[] date = rowDataList.get(3).split("/");
String dateString = date[2] +"-" +date[1] +"-" +date[0];
Date showDate = Date.valueOf(dateString);
int showTimeId = Integer.parseInt(rowDataList.get(4));
int cptId = Integer.parseInt(rowDataList.get(5));
int pcId = Integer.parseInt(rowDataList.get(6));
float amountPaid = Float.parseFloat(rowDataList.get(7));
int year = Integer.parseInt(rowDataList.get(8));
String month = rowDataList.get(9);
insertStatement.setInt(1, ticketID);
insertStatement.setInt(2, movieId);
insertStatement.setInt(3, theaterId);
insertStatement.setDate(4, showDate);
insertStatement.setInt(5, showTimeId);
insertStatement.setInt(6, cptId);
insertStatement.setInt(7, pcId);
insertStatement.setFloat(8, amountPaid);
insertStatement.setInt(9, year);
insertStatement.setString(10, month);
}
insertStatement.executeUpdate();
insertStatement.close();
}
//Method to update the data from the database
static void updateStatementt(String tableType, Connection conn, ArrayList <String> rowDataList) throws SQLException {
Statement statement = conn.createStatement();
String sql = "UPDATE " +tableType;
//There are other 'if' and 'else if' statements here for other tables
else if (tableType.equals("Tickets")) {
String[] date = rowDataList.get(3).split("/");
String dateString = date[2] +"-" +date[1] +"-" +date[0];
sql += " SET movie_id = " +rowDataList.get(1) +","
+ " theater_id = " +rowDataList.get(2) +","
+ " showdate = \"" +dateString +"\","
+ " showtime_id = " +rowDataList.get(4) +","
+ " costperticket_id = " +rowDataList.get(5) +","
+ " personcategory_id = " +rowDataList.get(6) +","
+ " amount_paid = " +rowDataList.get(7) +","
+ " year = " +rowDataList.get(8) +","
+ " month = \"" +rowDataList.get(9) +"\""
+ " WHERE ticket_id = " +rowDataList.get(0);
}
statement.executeUpdate(sql);
}
}
For short, read a single line and do whatever you want to do with it. You don't have enough memory for all 700k lines.
You should add statement.close() for the update Statement.
If you really want to read all this data into the Java heap, increase the heap size using, for example, the -Xmx command-line switch. Because of the way textual data is encoded in the JVM, you'll probably need much more heap that the total data size would suggest.
In addition, there might be some places in your code where you can take the strain off the JVM's memory management system. For example, concatenating strings using "+" can generate a lot of temporary data, which will increase the load on the garbage collector. Assembling strings using a StringBuilder might be a simple, less resource-hungry, alternative.

SQL Injection for array of mixed vulnerability and non vulnerability queries

Below persistent code has SQL vulnerability.
strSetStatement[1], strSetStatement[2] and strSetStatement[6] is setting parameters based on genSetStatement method sending. Which can be untrusted data. I am facing to fix this mix of simple queries and parameterized queries.
SQL Injection vulnerable code
public class SQLInjection{
public static void main(String[] args) throws SQLException, IOException {
String[] strSetStatement = new String[6];
PreparedStatement m_statement;
String url = "DBURL";
Connection conenction = DriverManager.getConnection(url, "", "");
m_statement = conenction.prepareStatement("SET CHARACTER_SET 'UTF8_FTCS'");
// Setting DB Initial parameters | setting limits for queries
String strMatch = "100";
String strTime = "100";
String strRank = "2:1";
genSetStatement(strSetStatement, strMatch, strTime, strRank);
boolean logQuery = true;
if (logQuery) {
for (int i = 0; i <= 7; i++)
setlogComment(m_statement, strSetStatement[i]);
}
}
private static void genSetStatement(String[] strSetStatement, String strMatch, String strTime, String strRank) {
strSetStatement[0] = "SET SHOW_MATCHES 'FALSE';";
strSetStatement[1] = "SET MAX_SEARCH_ROWS " + strMatch + ";";
strSetStatement[2] = "SET MAX_EXEC_TIME " + strTime + ";";
strSetStatement[3] = "SET SERVER_REPORT_TIME " + FTSSearchConst.SERVER_REPORT_TIME + ";";
strSetStatement[4] = "SET SEARCH_MEMORY_SIZE " + FTSSearchConst.SEARCH_MEMORY_SIZE + ";";
strSetStatement[5] = "SET THESAURUS_NAME 'FULTEXT';";
strSetStatement[6] = "SET RELEVANCE_METHOD '" + strRank + "';";
}
private static void setlogComment(PreparedStatement stmt, String strSetState) throws SQLException, IOException {
stmt.executeQuery(strSetState); // SQL injected area
}
}
I am trying to do below by adding '?' in strSetStatement[] array. and check if query has '?' in setlogComment method, but how to identify the exact parameter and bind variables to it ?
strSetStatement[1] = "SET MAX_SEARCH_ROWS " + ? + ";";
private static void setlogComment(PreparedStatement stmt, String strSetState) throws SQLException, IOException {
if(strSetState.contains("?")){
stmt.setString(1, arg1);
}
stmt.executeQuery(strSetState);
}
Caution: I'm not sure for which SQL version/dialect you're going to run these queries, this should be some Full-Text-Search extension.
The purpose of the following code is to get rid of the issues detected in your code snippet, however, you may need to update it appropriately in case of any error.
The code has been reactored to get rid of redundant methods/variables.
Queries at indexes 1, 2, 6 have been updated to include ? for outer parameters.
Type of matchRows and execTime parameters has been changed to int
Parameters for the PreparedStatement are set and the queries are executed inside main loop.
public class SQLInjection {
public static void main(String[] args) throws SQLException, IOException {
String[] strSetStatement = {
"SET SHOW_MATCHES 'FALSE';",
"SET MAX_SEARCH_ROWS ?;",
"SET MAX_EXEC_TIME ?;",
"SET SERVER_REPORT_TIME " + FTSSearchConst.SERVER_REPORT_TIME + ";",
"SET SEARCH_MEMORY_SIZE " + FTSSearchConst.SEARCH_MEMORY_SIZE + ";",
"SET THESAURUS_NAME 'FULTEXT';",
"SET RELEVANCE_METHOD ?;"
};
Connection connection = DriverManager.getConnection("DBURL", "", "");
PreparedStatement m_statement = connection.prepareStatement("SET CHARACTER_SET 'UTF8_FTCS'");
m_statement.executeQuery();
// Setting DB Initial parameters | setting limits for queries
int matchRows = 100;
int execTimeSec = 100;
String strRank = "2:1";
boolean logQuery = true;
if (logQuery) {
for (int i = 0; i < strSetStatement.length; i++) {
PreparedStatement stmt = connection.prepareStatement(strSetStatement[i]);
if (i == 1) {
stmt.setInt(1, matchRows);
} else if (i == 2) {
stmt.setInt(1, execTimeSec);
} else if (i == 6) {
stmt.setString(1, strRank);
}
stmt.executeQuery();
}
}
}
}

read cassandra data by paging doesn't work

I try to read cassandra data by paging, but it doesn't work. My codes are as below. I got the same content for every page. Anything I missed ?
// Persist the entity objects
for (int i=0; i<1000; i++) {
// change person1's id
personObj1.setPersonId("haofan" + i);
dataServiceClient.persist(personObj1);
}
Query query;
List<Person> personList;
// Create and execute SELECT * query
for (int i =0; i<10; i++) {
String cqlString = "Select p from Person p";
// String cqlString = "Select p from Person p";
query = dataServiceClient.createQuery(cqlString).setMaxResults(100).setFirstResult(i*100);
personList = query.getResultList();
// Get the same personId for every page.
Assert.assertEquals(100, personList.size());
System.out.println("haofan for: " + personList.get(10).getPersonId());
}
You are looking for offset queries there is no support on Cassandra natively.
I try multi solution, finally it works for me as below solution. Refer: https://docs.datastax.com/en/developer/java-driver/3.6/manual/paging/
public String paging(Session session, String pageState) {
Statement statement = new SimpleStatement("SELECT * FROM testkeyspace.\"PERSON\"");
statement.setFetchSize(3);
if (pageState != null) {
statement.setPagingState( PagingState.fromString(pageState));
}
ResultSet rs = session.execute(statement);
int remaining = rs.getAvailableWithoutFetching();
System.out.println("remaining " + remaining);
for (Row row : rs) {
System.out.println("first" + row);
if (--remaining == 0) {
break;
}
}
return rs.getExecutionInfo().getPagingState().toString();
}
How to use this function:
#Test
#Category(DataServiceRequired.class)
public void pagingTest() throws Exception {
Cluster cluster = Cluster.builder().addContactPoint("localhost").withPort(9042).build();
Session session = cluster.connect();
String pageState = paging(session, null);
paging(session, pageState);
}

Can't print output through loop, don't know how to print second table

Edit: anything would help. If anyone can tell me the process at least I'd appreciate it.
I'm trying to get my code to read for an access database that I made. In that database are 2 tables, one is Soccer_Team and the other is Soccer_Players. I'm having an issue figuring out how to have the field name show up in front of the actual data. When I run the code now I get this:
Name: Location: Home Stadium: FC Barcelona Spain Camp Nou
Name: Location: Home Stadium: FC Bayern Munich Germany Allianz
I want the "Name:" to be followed by the club name, and so on... I am not familiar with Java so I am a little confused here.
Also, I want to print the second table from my database through an SQL query, that has it display the above but with the player information printed under each row... I don't even know where to begin doing that. I'm not sure I'm explaining this well, so sorry if I'm confusing people.
Sorry if this is asking too much but I am pretty lost... Thanks for any help guys.
package msjavaaccessdb;
import java.sql.*;
import java.util.*;
public class MSjavaAccessDB {
/** Creates a new instance of databaseApplication */
public MSjavaAccessDB() {
}
/**
* #param args the command line arguments
*/
static String nameOfJdbcOdbcDriver =
"sun.jdbc.odbc.JdbcOdbcDriver";
// static String dataBaseNameDSN = "jdbc:odbc:myDataSource";
static String dataBaseNameDSN = "jdbc:odbc:myDataSource";
static String userName = "";
static String passwordForUser = "";
static Connection myConnectionRequest = null;
static Statement myStatementObject = null;
static ResultSet myResultTuples = null;
static ResultSetMetaData myResultTuplesMetaData = null;
static String queryToBeExecuted = "select * from Soccer_Team";
public static void main(String args[])
throws ClassNotFoundException {
try {
//Identify the driver to use
Class.forName(nameOfJdbcOdbcDriver);
//Attempt a connection to database...
Connection myConnectionRequest =
DriverManager.getConnection(
dataBaseNameDSN, userName, passwordForUser);
//Create a statement object, use its method to execute query
Statement myStatementObject =
myConnectionRequest.createStatement();
//Use statement object method to execute a query.
//Hold results in a resutl set...like a cursor
ResultSet myResultTuples = myStatementObject.executeQuery
(queryToBeExecuted);
//Call metadata to get the number of attributes
myResultTuplesMetaData = myResultTuples.getMetaData();
int numberOfAttributes =
myResultTuplesMetaData.getColumnCount();
System.out.println(Integer.toString(numberOfAttributes));
//For each row in result set, print ALL columns
for(int rowNum = 1; myResultTuples.next(); rowNum++) {
for (int i = 1; i <= numberOfAttributes; i++) {
if ( (i != 1) ) System.out.print (
myResultTuples.getString(i) + "\t");
else {//String xyz = myResultTuples.getString(1);
int xyz = Integer.parseInt( myResultTuples.getString(1));
System.out.print ("Name: ");
System.out.print ("Location: ");
System.out.print ("Home Stadium: ");
}
}
System.out.println("\n\n");
}
} // end of try block
//handle ALL exceptions to above database calls
catch (SQLException sqlError) {
System.out.println("Unexpected exception : " +
sqlError.toString() + ", sqlstate = " +
sqlError.getSQLState());
sqlError.printStackTrace();
}
} // end of main method of this class
} // end of the class
So I don't know how your datatable looks, but what i guess you want to do is print the column label and then the corresponding data value of the row.
for(int rowNum = 1; myResultTuples.next(); rowNum++) {
for (int i = 1; i <= numberOfAttributes; i++) {
//print column label
System.out.print(myResultTuplesMetaData.getColumnLabel(i) + ": ");
//print data value
System.out.print(myResultTuples.getString(i) + "\t");
}
System.out.println("\n\n");
//process SQl-Query about players and print out results in another for loop HERE
}
So for the second table you would have to do sth like SELECT * FROM table2 WHERE team IS (?) as a PreparedStatement and print out the results in another loop.
I can't get the error right now because I don't have access to NetBeans at this moment. I can update later when I am on my home computer. I'm not sure if what I did makes sense, because I don't exactly know what the rules of Java are... Hope this isn't stroke inducing.
package msjavaaccessdb;
import java.sql.*;
import java.util.*;
public class MSjavaAccessDB {
/** Creates a new instance of databaseApplication */
public MSjavaAccessDB() {
}
/**
* #param args the command line arguments
*/
static String nameOfJdbcOdbcDriver =
"sun.jdbc.odbc.JdbcOdbcDriver";
static String dataBaseNameDSN = "jdbc:odbc:myDataSource";
static String dataBaseNameDSN = "jdbc:odbc:myDataSource";
static String userName = "";
static String passwordForUser = "";
static Connection myConnectionRequest = null;
static Statement myStatementObject = null;
static ResultSet myResultTuples = null;
static ResultSetMetaData myResultTuplesMetaData = null;
static ResultSet ResultTuples = null;
static ResultSetMetaData ResultTuplesMetaData = null;
static String queryToBeExecuted = "select * from Soccer_Team";
static string secondQuery = "select * from Soccer_Player where team is (?)";
public static void main(String args[])
throws ClassNotFoundException {
try {
//Identify the driver to use
Class.forName(nameOfJdbcOdbcDriver);
//Attempt a connection to database...
Connection myConnectionRequest =
DriverManager.getConnection(
dataBaseNameDSN, userName, passwordForUser);
//Create a statement object, use its method to execute query
Statement myStatementObject =
myConnectionRequest.createStatement();
//Use statement object method to execute a query.
//Hold results in a resutl set...like a cursor
ResultSet myResultTuples = myStatementObject.executeQuery
(queryToBeExecuted);
ResultSet ResultTuples = myStatementObject.executeQuery
(secondQuery);
//Call metadata to get the number of attributes
myResultTuplesMetaData = myResultTuples.getMetaData();
int numberOfAttributes =
myResultTuplesMetaData.getColumnCount();
System.out.println(Integer.toString(numberOfAttributes));
ResultTuplesMetaData = ResultTuples.getMetaData();
int numOfAttributes =
ResultTuplesMetaData.getColumnCount();
System.out.println(Integer.toString(numOfAttributes));
//For each row in result set, print ALL columns
for(int rowNum = 1; myResultTuples.next(); rowNum++) {
for (int i = 1; i <= numberOfAttributes; i++) {
//print column label
System.out.print(myResultTuplesMetaData.getColumnLabel(i) + ": ");
//print data value
System.out.print(myResultTuples.getString(i) + "\t");
}
System.out.println("\n\n");
}
for(int rowNum = 1; ResultTuples.next(); rowNum++) {
for (int i = 1; i <= numOfAttributes; i++) {
//print column label
System.out.print(ResultTuplesMetaData.getColumnLabel(i) + ": ");
//print data value
System.out.print(ResultTuples.getString(i) + "\t");
}
System.out.println("\n\n");
}
} // end of try block
//handle ALL exceptions to above database calls
catch (SQLException sqlError) {
System.out.println("Unexpected exception : " +
sqlError.toString() + ", sqlstate = " +
sqlError.getSQLState());
sqlError.printStackTrace();
}
} // end of main method of this class
} // end of the class

Fail to convert to internal representation JDBC

Ok so this is my code
public static ArrayList getMaterialerFraOrdreNr(String s_date, String e_date) throws SQLException, InterruptedException {
int tal = 0;
ArrayList nameOfColumns = getNameOfColumns(); // name of columns
ArrayList orderNumber = getOrdre_Nr_FromDB(s_date, e_date); // order number
//første loop kører gennem number of columns
//anden loop kører gennem name of column
ResultSet rs = null;
Connection con = null;
try {
Class.forName(DB.driver);
con = DriverManager.getConnection(DB.URL, DB.ID, DB.PW);
for (int i = 1; i < orderNumber.size(); i++) {
for (int j = 1; j < nameOfColumns.size(); j++) {
String nameOfColum = (String) nameOfColumns.get(i);
int orderNr = (Integer) orderNumber.get(j);
System.out.println("orderNr " + orderNr);
//SELECT v1001 FROM ORDRE_spec WHERE ordre_nr = 1;
String query = "SELECT ? AS ans FROM ordre_spec WHERE ordre_nr = ?";
PreparedStatement prest = con.prepareStatement(query);
prest.setString(1, nameOfColum);
prest.setInt(2, orderNr);
System.out.println("orderNr " + orderNr);
System.out.println("nameOfColum = " + nameOfColum);
rs = prest.executeQuery();
if(rs.next()){
tal = rs.getInt("ans");
MaterialeNum.add(tal);
System.out.println("materiale num = " + MaterialeNum);
}
}
}
} catch (ClassNotFoundException | SQLException ee) {
System.out.println("fail og der er så her");
System.err.println(ee);
} finally {
con.close();
}
System.out.println(kundeNum.toString());
return kundeNum;
}
public static void main(String[] args) throws SQLException, InterruptedException {
NewClass.getMaterialerFraOrdreNr("1990-10-10", "2020-10-10");
}
And my problem is that I'm getting a java.sql.SQLException: Fail to convert to internal representation
I really cant see what the error should be.. plz help if you can see the error :)
String query = "SELECT ? AS ans FROM ordre_spec WHERE ordre_nr = ?";
You cannot parameterize column names. You can only parameterize column values.
Basically you need to do:
String query = "SELECT " + nameOfColum + " AS ans FROM ordre_spec WHERE ordre_nr = ?";
Keep in mind that this is prone to SQL injection if nameOfColum is controllable by enduser. If this is indeed the case, you may want to perform string matching on e.g. \w+ before continuing.

Categories