Iterartor - How to traverse for specific records - java

I have executed a query using JDBC and traversing the resultset I have stored all fields in List in java.
List<String> dataList=new ArrayList<String>();
while(res.next())
{
dataList.add(res.getString(1));
dataList.add(res.getString(2));
dataList.add(res.getString(3));
dataList.add(res.getString(4));
dataList.add(res.getString(5));
dataList.add(res.getString(6));
dataList.add(res.getString(7));
}
Iterator<String> it= dataList.iterator();
As I have added directly into list so how can I get this 7 fields while traversing the iterator.
Means:
while(it.hasNext())
{
String f1=it.next();
}
Like wise everytime I want 7 fields at a time
and next 7, next 7....... so on
Using this while loop how can I get those 7 fields (one row in table having 7 field) at a time.
I get little bit confuse here. Please help me.
Thanks

What you want to do is actually create another object that stores all seven of the values.
Then create a list of these entries so that you can access one row at a time, which is what I think you are asking.
First create a class for the row.
private static class Entry {
String[] row;
public Entry ( ResultSet r ) {
row = new String [ 7 ];
for (int i = 1; i <= 7; i++) {
row[i] = r.getString(i);
}
}
}
Using that, you can then create a list of Entry objects.
List<Entry> entryList = new ArrayList <Entry> ();
while(res.next())
{
entryList.add ( new Entry ( res ) );
}
Then, you can go ahead and loop through entryList and get any specific entry you would want.
Of course, if you have specific values, it might be wise to create instance variables of type String for Entry rather than an array of Strings.
By that I mean you could do this:
private static class Entry {
String column1; // rather than name column1 use what the column semantically represents
String column2;
// ...
public Entry ( ResultSet r ) {
column1 = r.getString(1);
// ...
}
This way, you can also calls like r.getInt(i) for certain columns which have an different type other than String.
Good luck!

I think your List declaration should be
List<Any DAO Object> instead of List<String>
While fetching from resultset, create a DAO object, add all fetched data into that object and then add that object into the list.
Then you can iterate and get each DAO object at each iteration.

You can use DatabaseMetaData class,
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost/testdb";
private static final String USERNAME = "root";
private static final String PASSWORD = "";
public static void main(String[] args) throws Exception {
Class.forName(DRIVER);
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
DatabaseMetaData metadata = connection.getMetaData();
ResultSet resultSet = metadata.getColumns(null, null, "users", null);
while (resultSet.next()) {
String name = resultSet.getString("COLUMN_NAME");
String type = resultSet.getString("TYPE_NAME");
int size = resultSet.getInt("COLUMN_SIZE");
System.out.println("Column name: [" + name + "]; type: [" + type + "]; size: [" + size + "]");
}
connection.close();
}

Related

returning 2 different values

i'm working with java in eclipse.I am trying to take 2 variables from my database and write it to an excel.My only problem is returning 2 different values(an integer and a string) from db reader method and send it to excel writer method which are in different classes.
Here is my db reader class:
public class DbConnection {
public void createConnection(String choice) {
try {
String myDriver = "com.mysql.jdbc.Driver";
String db = "jdbc:mysql://localhost/digiturkschema";
Class.forName(myDriver);
Connection conn = DriverManager.getConnection(db, "root",
"*****");
Statement st = conn.createStatement();
switch (choice) {
case "write":
ResultSet rs = st.executeQuery("SELECT * FROM channelstable");
while (rs.next()) {
int channelId = rs.getInt("channelNo");
String channelName = rs.getString("channelName");
}
}
} catch (Exception exception) {
System.out.print(exception.getStackTrace());
}
}
}
I need to return "channelId" and "channelName" from this method to this method:
public class WritingToExcel {
public void Write() throws IOException {
try {
JFileChooser f = new JFileChooser();
f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
f.showSaveDialog(null);
System.out.println(f.getCurrentDirectory());
System.out.println(f.getSelectedFile());
String direction = f.getSelectedFile().toString() + "\\DigiTurkKanalListesi.xls";
WritableWorkbook workbook = Workbook.createWorkbook(new File(direction));
WritableSheet sheet = workbook.createSheet("Kanal Listesi", 0);
Label label = new Label(0, 0, "A label record");
sheet.addCell(label);
Number number = new Number(2, 1, 3.1459);
sheet.addCell(number);
workbook.write();
workbook.close();
} catch (WriteException e) {
e.getStackTrace();
}
}}
I know that writingToExcel class is not completed and it's ok,i can finish it if i can take these two variables to this class.By the way i am using MVC pattern so i have a controller class between them.I can write it too if it's necessary.
As #Ascalonian said, you can use Map or HashMap.
for example:
Map<Integer, String> channelInfo = new HashMap<Integer, String>();
You can also (but should not):
Create a new class with the values you need and return that class. (You will be doing extra work which you don't really need to.)
Create setter methods for those variables and use it before calling the method to write to excel. (requires caution as you can end up with undesired values if you mess the code)
There are multiple options
ArrayList<Objects> : During Iterating the resultSet prepare temporary List say tempList insert items into tempList and then after each iteration add tempList to Main List , Since ArrayList is a sequential list. So, insertion and retrieval order is the same. So you can return this from your dbReader() method .Then use them wherever you want
Your Arraylist will look like this
[ [1,Channel 1] , [2,Channel 2] , [3,Channel 3] ]
Map if order is important prefer LinkedHashMap if order is not your primary concern then opt for HashMap

InvalidTypeException: Invalid type for value 1 of CQL type text, expecting class java.lang.String but class [Ljava.lang.Object; provided

I am trying to insert into Cassandra database using Datastax Java driver. But everytime I am getting below exception at prBatchInsert.bind line-
com.datastax.driver.core.exceptions.InvalidTypeException: Invalid type for value 1 of CQL type text, expecting class java.lang.String but class [Ljava.lang.Object; provided
Below is my method which accepts userId as the input and attributes as the Map which contains key as my Column Name and value as the actual value of that column
public void upsertAttributes(final String userId, final Map<String, String> attributes, final String columnFamily) {
try {
Set<String> keys = attributes.keySet();
StringBuilder sqlPart1 = new StringBuilder(); //StringBuilder.append() is faster than concatenating Strings in a loop
StringBuilder sqlPart2 = new StringBuilder();
sqlPart1.append("INSERT INTO " + columnFamily + "(USER_ID ");
sqlPart2.append(") VALUES ( ?");
for (String k : keys) {
sqlPart1.append(", "+k); //append each key
sqlPart2.append(", ?"); //append an unknown value for each key
}
sqlPart2.append(") "); //Last parenthesis (and space?)
String sql = sqlPart1.toString()+sqlPart2.toString();
CassandraDatastaxConnection.getInstance();
PreparedStatement prBatchInsert = CassandraDatastaxConnection.getSession().prepare(sql);
prBatchInsert.setConsistencyLevel(ConsistencyLevel.ONE);
// this line is giving me an exception
BoundStatement query = prBatchInsert.bind(userId, attributes.values().toArray(new Object[attributes.size()])); //Vararg methods can take an array (might need to cast it to String[]?).
CassandraDatastaxConnection.getSession().executeAsync(query);
} catch (InvalidQueryException e) {
LOG.error("Invalid Query Exception in CassandraDatastaxClient::upsertAttributes "+e);
} catch (Exception e) {
LOG.error("Exception in CassandraDatastaxClient::upsertAttributes "+e);
}
}
What wrong I am doing here? Any thoughts?
You need to combine the userId string to the object array, because the way you are passing it now is being seen as [string, object array] and java doesn't like that.
// instead of
// BoundStatement query = prBatchInsert.bind(userId, attributes.values().toArray(new Object[attributes.size()]));
// try, first combining the uid to the map of values
Collection<Object> params = new ArrayList<Object>(attributes.size() + 1);
params.add(userId);
for(Object o : attributes.values().toArray())
params.add(o);
// then passing in the new collection as an array
BoundStatement query = prBatchInsert.bind(params.toArray());

How to generate a sql from the inputs to the method

I have my below method which will accept two parameters-
final String userId- Primary Key for the database
final Collection<String> attributeNames- list of column names that I
want to retrieve
Below is the code
public Map<String, String> getAttributes(final String userId, final Collection<String> attributeNames) {
//Below line doesn't works out the way I wanted
String query="SELECT" +attributeNames.toString()+ ", * from test where id = "+userId+ ";";
ResultSet result = CassandraDatastaxConnection.getInstance().getSession().execute(query);
for (Row rows: result){
System.out.println(rows.getString("key"));
}
return attributes;
}
let's take an example, userId as 40
Sample attributeNames will look like this-
[account, behavior, segmentation]
Now I need to generate a SQL corresponding to the inputs. So for above example, sql should look like this-
SELECT account, behavior, segmentation from test where id = "40";
How can I generate a SQL like this from the above inputs? Thanks for the help.
You can use something like attributeNames.toString().substring(1, attributeNames.toString().length()-1)
Change this function
public Map<String, String> getAttributes(final String userId, final Collection<String> attributeNames) {
//Below line doesn't works out the way I wanted
String query="SELECT" +attributeNames.toString()+ ", * from test where id = "+userId+ ";";
ResultSet result = CassandraDatastaxConnection.getInstance().getSession().execute(query);
for (Row rows: result){
System.out.println(rows.getString("key"));
}
return attributes;
}
to this
public Map<String, String> getAttributes(final String userId, final Collection<String> attributeNames) {
//Below line doesn't works out the way I wanted
StringBuilder sb = new StringBuilder(attributeNames.size());
for(int i = 0; i<attributeNames.size();i++)
{
sb.append(attributeNames.get(i));
if(i != attributeNames.size() - 1)
sb.append(",");
}
String query="SELECT" +sb.toString()+ " from test where id = "+userId+ ";";
ResultSet result = CassandraDatastaxConnection.getInstance().getSession().execute(query);
for (Row rows: result){
System.out.println(rows.getString("key"));
}
return attributes;
}
The modified function runs a loop through the attribute names and constructs the query part as name1, name2, name3, etc and then adds it to the query body. Hope this solves your problem.

Single thread writing to different database with different connection parameters

I am working on a project in which I have three tables in a different database with different schemas. So that means I have three different connection parameters for those three tables to connect using JDBC-
Let's suppose-
For Table1-
Username:- A
Password:- B
URL: C
Columns-
ID1 String
Account1 String
For Table2-
Username:- P
Password:- Q
URL:- R
Columns-
ID2 String
Account2 String
For Table3-
Username:- T
Password:- U
URL:- V
Columns-
ID3 String
Account3 String
And I am supposed to insert in all the three tables or any one of them using JDBC.
Below are the three use cases I have-
From the command prompt if suppose I am passing Table1 only, then I am suppose to insert only in Table1 columns by making connection to
Table1.
And if I am passing Table1, Table2 from the command prompt then I am suppose to insert in both Table1 and Table2 columns by making
connection to Table1 and Table2.
And if I am passing Table1, Table2 and Table3 then I am suppose to enter in all the three tables using there respective connection
parameter
I am not able to understand how to write code for the above particular scenario in such a cleaner way so that it can be extended in near future as well if I come up with four tables. I can have a one constant file which can store the SQL that needs to be executed for any of the three tables and some other constant thing as well.
public static void main(String[] args) {
}
class Task implements Runnable {
private Connection dbConnection = null;
private PreparedStatement preparedStatement = null;
public Task() {
}
#Override
public void run() {
dbConnection = getDbConnection();
//prepare the statement and execute it
}
}
private Connection getDBConnection() {
Connection dbConnection = null;
Class.forName(Constants.DRIVER_NAME);
dbConnection = DriverManager.getConnection( , , );
return dbConnection;
}
Can anyone provide some thoughts on this how should I proceed forward?
Note:-
Column in each table will differ a lot. Like in some tables, column can be 10 and in some other table, column can be 20.
Create databases.properties file with content like this:
# Table 1
table1.url: jdbc:mysql://localhost:3306/garden
table1.user: gardener
table1.password: shavel
table1.table: fruits
table1.column.id: fruitID
table1.column.color: fruitColor
table1.column.weight: fruitWeight
# ... More fruit columns here ...
# Table 2
table2.url: jdbc:mysql://otherhost:3306/forest
table2.user: forester
table2.password: axe
table2.table: trees
table2.column.id: treeID
table2.column.height: treeHeight
# ... More tree columns here ...
# ... More tables here ...
Then do something like this:
public static void main (String [] args)
{
Properties databasesProperties = new Properties ();
databasesProperties.load ("databases.properties");
for (String arg: args)
{
String url = databasesProperties.get (arg + ".url");
String user = databasesProperties.get (arg + ".user");
String password= databasesProperties.get (arg + ".password");
String table = databasesProperties.get (arg + ".table");
String columnPrefix = arg + ".column."
Map <String, String> columns = new HashMap <String, String> ();
for (String key: databasesProperties.stringPropertyNames ())
{
if (key.startsWith (columnPrefix))
columns.put (
key.substring (columnPrefix.length ()),
databasesProperties.get (key));
}
doInsert (url, user, password, table, columns);
}
}
Later you can always add more tables into your databases.properties file.
Save your Database properties in a class file DBPropery.java.
final class DBProperty
{
static String[] urls = {
"C",
"R",
"V"
}; //You can add more URLs here.
static String[] driver= {
"Driver1",
"Driver2",
"Driver3"
};//You can add more drivers string
static String[] table = {
"Table1",
"Table2",
"Table3"
};//You can add more table names here According to URLs mentioned in urls array.
static String[] user = {
"A",
"P",
"T"
};//You can add more user names here according to URls mentioned in urls array.
static String[] pwd = {
"B",
"Q",
"U"
};//You can add more Password here according to URls mentioned in urls array.
static String[] queries = {
"Query for Table1",
"Query for Table2",
"Query for Table3",
};//You can add more queries here for more tables according to URls mentioned in urls array.
static int[] columns ={
2,
2,
2
};//You can change the column numbers according to need . 0th index belongs to Table1 , 1 to table2....so on.
//If you add more tables , add corresponding columns count to next index.
static String[] columnValues ={
"1^John",
"34^Vicky",
"65^Ethen"
};//String at each index represents a row in corresponding table in table[] array. each column is seperated by delimiter "^".
}
Make all Changes in DBProperty.java file.
Then proceed with following class file
import java.sql.*;
import java.util.*;
class MultiTableInsert implements Runnable
{
Map<String,Integer> columnsInTable;
Map<String,String> tableDriver;
Map<String,String> rowForTable;
Map<String,String> queryForTable;
Map<String,String> urlForTable;
Map<String,String> userForTable;
Map<String,String> pwdForTable;
String[] tables ;
public MultiTableInsert(String... tables)//Loading all Database Settings here..
{
this.tables = tables;
columnsInTable = new LinkedHashMap<String,Integer>();
rowForTable = new LinkedHashMap<String,String>();
tableDriver = new LinkedHashMap<String,String>();
urlForTable = new LinkedHashMap<String,String>();
userForTable= new LinkedHashMap<String,String>();
pwdForTable = new LinkedHashMap<String,String>();
for (int i = 0 ; i < DBProperty.urls.length ; i++ )
{
try
{
tableDriver.put(DBProperty.table[i],DBProperty.driver[i]);
queryForTable.put(DBProperty.table[i],DBProperty.queries[i]);
columnsInTable.put(DBProperty.table[i],DBProperty.columns[i]);
rowForTable.put(DBProperty.table[i],DBProperty.columnValues[i]);
urlForTable.put(DBProperty.table[i],DBProperty.urls[i]);
userForTable.put(DBProperty.table[i],DBProperty.user[i]);
pwdForTable.put(DBProperty.table[i],DBProperty.pwd[i]);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
#Override
public void run()
{
insertIntoTable(tables);
}
private void insertIntoTable(String... tables)
{
for (String tble : tables )
{
Connection con = null;
PreparedStatement pStmt = null;
try
{
Class.forName(tableDriver.get(tble));
con = DriverManager.getConnection(urlForTable.get(tble),userForTable.get(tble),pwdForTable.get(tble));
pStmt = con.prepareStatement(queryForTable.get(tble));
int columns = columnsInTable.get(tble);
String sRow = rowForTable.get(tble);
StringTokenizer tokenizer = new StringTokenizer(sRow,"^");
for (int i = 0; i < columns ; i++)
{
pStmt.setString(i+1,(String)tokenizer.nextElement());
}
pStmt.execute();
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
try
{
con.close();
}catch (Exception ex){}
try
{
pStmt.close();
}catch (Exception ex){}
}
}
}
public static void main(String[] args)
{
int length = args.length;
int THREAD_COUNTS = 10;//Number of threads you want to start.
switch (length)
{
case 0:
System.out.println("Usage: javac MultiTableInsert Table1/Table2/Table3 <Table1/Table2/Table3> <Table1/Table2/Table3>");
System.exit(0);
case 1:
for (int i = 0 ; i < THREAD_COUNTS ; i++)
{
MultiTableInsert mti = new MultiTableInsert(args[0]);
Thread th = new Thread(mti,"Thread"+i);//Create New Thread
th.start(); //Start Thread
}
break;
case 2:
for (int i = 0 ; i < THREAD_COUNTS ; i++)
{
MultiTableInsert mti = new MultiTableInsert(args[0],args[1]);//Create New Thread
Thread th = new Thread(mti,"Thread"+i); //Start Thread
th.start();
}
break;
default:
for (int i = 0 ; i < THREAD_COUNTS ; i++)
{
MultiTableInsert mti = new MultiTableInsert(args[0],args[1],args[2]);//Create New Thread
Thread th = new Thread(mti,"Thread"+i); //Start Thread
th.start();
}
break;
}
}
}

Java Custom ArrayList All Entries the Same

I have a custom an arraylist setup to hold data for me.
However when I call the arraylist items all the items are the same.
My arraylist loader.
public static ArrayList<Animal> getTblHerd() throws Exception {
CC_H2 db = new CC_H2();
db.Connect(Variables.getStrConn(), Variables.getStrUser(),
Variables.getStrPassword(), "Embedded");
ResultSet rs = db.query("Select HERD_ID FROM tblHerd ORDER BY HERD_ID ASC");
ArrayList<Animal> alAnimals = new ArrayList<Animal>();
while (rs.next()) {
int i = rs.getInt("HERD_ID");
alAnimals.add(new Animal(i));
}
db.Disconnect();
return alAnimals;
}
Animal Constructor
public Animal(int intAnimal_ID) throws Exception{
CC_H2 db = new CC_H2();
db.Connect(Variables.getStrConn(), "admin", "", "Embedded");
ResultSet rs = db.query("Select * FROM tblHerd WHERE HERD_ID = "
+ intAnimal_ID);
while (rs.next()) {
setIntHerd_id(rs.getInt("Herd_ID"));
setStrHerd_Tag_Letter(rs.getString("Herd_Tag_Letter"));
setIntHerd_Tag_Num(rs.getInt("Herd_Tag_Num"));
setStrHerd_Tag_Color(rs.getString("Herd_Tag_Color"));
setStrHerd_Sex(rs.getString("Herd_Sex"));
setStrHerd_Type(rs.getString("Herd_Type"));
setDtHerd_Birthdate(rs.getDate("Herd_Birthdate"));
setIntHerd_Sire(rs.getInt("Herd_Sire"));
setIntHerd_Dam(rs.getInt("Herd_Dam"));
setIntHerd_Owner(rs.getInt("Herd_Owner"));
setDtHerd_TimeStamp(rs.getDate("Herd_TimeStamp"));
setStrHerd_Status(rs.getString("Herd_Status"));
setDtHerd_Status_Date(rs.getDate("Herd_Status_Date"));
}
db.Disconnect();
}
I think the code you listed should work as expected, the error is probably somewhere else.
Check the data in your database
Check the setters in the while loop do the right thing
Check that the fields in the Animal class are not static
If the problem persists, try to put something like System.out.println(rs.getInt("Herd_ID") + ": " + rs.getString("Herd_Tag_Letter")); into the where loop and check the output
Hope some of this helps :-)
you have created array list static
just remove static from there

Categories

Resources