I had an issue in building the resultset using Java.
I am storing a collection object which is organized as row wise taken from a resultset object and putting the collection object (which is stored as vector/array list) in cache and trying to retrieve the same collection object.
Here I need to build back the resultset again using the collection object. Now my doubt is building the resultset in this way possible or not?
The best idea if you are using a collection in place of a cache is to use a CachedRowSet instead of a ResultSet. CachedRowSet is a Subinterface of ResultSet, but the data is already cached. This is far simpler than to write all the data into an ArrayList.
CachedRowSets can also be queried themselves.
CachedRowSet rs;
.......................
.......................
Integer id;
String name;
while (rs.next())
{
if (rs.getInt("id") == 13)
{
id = rs.getInt("id");
name = rs.getString("name"));
}
}
So you just call the CachedRowSet whenever you need the info. It's almost as good as sliced bread. :)
EDIT:
There are no set methods for ResultSet, while there are Update methods. The problem with using the Update method's for the purpose of rebuilding a ResultSet is that it requires selecting a Row to update. Once the ResultSet has freed itself, all rows are set to null. A null reference cannot be called. A List of Lists mimics a ResultSet itself, or more correctly, an array of arrays mimic a ResultSet.
While Vectors are thread safe, there is a huge overhead attached to them. Use the ArrayList instead. As each nested List is created and placed into the outer nest List, insert it in this manner.
nest.add(Collections.unmodifiableList(nested));
After all of the nested Lists are inserted, return the nest List as an umodifiableList as well. This will give you a thread-safe collection without the overhead of the vectors.
Take a look at this page. Try to see if the SimpleResultSet class is fine for your needs.
If you combine its source into a standalone set of classes, it should do the trick.
From what I could get, your code may be like this:
List collection = new ArrayList();
collection.add(" A collection in some order");
List cache = new ArrayList();
cache.add(collection); ...
Now when you retrieve I think you'll get your collection in order, since you have used List.
If this is not what you were expecting, do comment.
I will advise you to use CachedRowSet. Refer http://www.onjava.com/pub/a/onjava/2004/06/23/cachedrowset.html this article to know more about CachedRowSet. Once you create this CachedRowSet, you can disconnect from the database, make some changes to the cached data and letter can even open the DB connection and commit the changes back to the Database.
Another option you should consider is just to refactor your code to accept a Collection instead of a ResultSet.
I'm assuming you pass that ResultSet to a method that iterates over it. You might as well change the method to iterate over an ArrayList...
Related
I have set up a Cassandra connection through Java driver. And I want to retrieve an entire row as a collection. I want to get rid of using getString() or getInt() always. When I give a query saying select all columns in the users table using CQL. the entire result should be sent to a collection rather than a string. How do I achieve this?
I have done the following to retrieve the columns. It gives me the proper results. But I want to retrieve the entire row as a collection.
Outside the for loop I want to retrieve these fields as one object. How do I do this??
String name=null;
String age=null;
ResultSet results = session.execute("SELECT * FROM admin.users");
for (Row row : results) {
name=row.getString("firstname");
age=row.getString("age");
System.out.println("name::"+name);
System.out.pintl("age::"+age);
}
If you want to obtain all fields in a collection you could use getMap(..) function and you will get a Map with keys and values.
On the other hand, check new object Mapping API since version 2.1 and you can map a class directly from ResultSet with annotations in your entity class.
I have a very common encapsulation problem. I am querying a table through jdbc and needs to hold the records in memory for sometime for processing.I dont have any hibernate POJO for the same table to create any objects and save.I am talking about a load of say 200 million in a single query.
The common approach is to create an object array and do casting when I need to use them. (Assume, I can get the table details like column name and data type which will be saved in some reference tables..) But this approach will be very expensive (Time) I guess when the load is taken into consideration..
Any good approach will be appreciated...
Sounds like a CachedRowSet would do the trick here. That's pretty much exactly what you want. It will take a ResultSet and suck the entire thing down, then you can work on it at your leisure.
Addenda:
I am really looking for a robust record holder with easy access on the members
But that's pretty much exactly what a CachedRowSet is.
It manages a collection of records with named (and numbered) columns, and provides typed access to those columns.
CachedRowSet crs = getACachedRowSet();
crs.absolute(5) // go to 5th row, shows you have random access to the contents.
String name = crs.getString("Name");
int age = crs.getInt("Age");
date dob = crs.getDate("DateOfBirth");
While I'm sure you can make up something on your own, a CachedRowSet gives you everything you've asked for. If you don't want to actually load the data in to RAM, you could just use a ResultSet.
Only down side is that it's not thread safe, so you'll need to synchronize around it. But that's life. How exactly does a CachedRowSet not meet your needs?
Well, if you need 200m objects in memory then you can initialize each while iterating through the ResultSet - you don't need to save the metadata
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
String col1= rs.getString("col1");
Integer col2= rs.getInt("col2");
MyClass o = new MyClass(col1,col2);
add(o);
}
rs.close();
To make it more clear, the table involved is completely configurable.
That is why I cant create POJO classes prior to this task.
In that case, I'd have thought that the only real way of doing this is to turn each row into a string with delimiters (CSV, XML or something) and then create an array of strings.
You can get a list of column names returned by a JDBC query as in this answer:
Retrieve column names from java.sql.ResultSet
I have obtained a ResultSet for some query, e.g:
select * from students order by roll
Now, is it possible to perform an equivalent of query
Select * from students order by dob;`
on the ResultSet?
As rule of thumb (well, almost) everything that can be done in the DB should be done there, so you should sort your data in the DB using the ... ORDER BY <column1>, <COLUMN2>... ASC/DESC
But if for some reason you cannot do that you should extract all the data from the RS into a collection (and may be map your data to domain objects) and sort it using the Collections.sort() method with an appropriate Comparator
It will be very not recommended to do the Sort after the query (ie. When you're getting the ResultSet).
You should always aim to do actions on the SQL Server rather on the code itself.
ResultSet are some kind of Iteration objects, that means that you can only move one by one. Thus, in order to Sort it, you first need to shift the data into a Collection and only then use Sorting on it.
Compare to SQL Sorting this is overhead and can be avoided.
Get an ArrayList from your ResultSet by iterating over your result and adding it to a a new list.
Then useCollections.sort(Collection, Comparator) to sort your result
I have started using JPA 2 / JPQL. I see a lot of examples where query.getResultList() is returned. But have never seen the resultlist marked as unmodifiable. For instance:
final TypedQuery<String> query = entityManager.createNamedQuery("Some query", String.class); //$NON-NLS-1$
return query.getResultList();
Is there any reason this should not be marked as unmodifiable, if I dont expect to change the result set returned from the database?
Any reason this could cause issues?
It's more there's no reason to mark it as unmodifiable. If you want to change the contents of the list, feel free, it's just the results from a database.
The list in the query object has no reason to make it unmodifiable. It's just an in memory store of what's in the database at that point so modifying this list doesn't make changes to the database unless you actually persist this new list.
I have Employee table and an Entity class for it,
My task is such that i need the data of employee table within result set(of type scrollable) two times,
in such case what would be better of the following for using the data second time ->
1: create instance of entity class and store it in List while iterating through result set for first time.
OR
2: after first iteration call the first() method of result set to go back to first row and use data for second time.
Which option will consume less time and resources.
If You have better suggestions, please provide.
Thanks.
Unless this is about very large resultsets, you're probably much better off consuming the whole JDBC ResultSet into memory and operating on a java.util.List rather than on a java.sql.ResultSet for these reasons:
The List is more user-friendly for developers
The database resource can be released immediately (which is less error-prone)
You will probably not run out of memory in Java on 1000 rows.
You can make many many mistakes when operating on a scrollable ResultSet, as various JDBC drivers implement this functionality just subtly differently
You can use tools for consuming JDBC result sets. For instance Apache DbUtils:
QueryRunner run = new QueryRunner(dataSource);
ResultSetHandler<List<Person>> h
= new BeanListHandler<Person>(Person.class);
List<Person> persons = run.query("SELECT * FROM Person", h);
jOOQ (3.0 syntax):
List<Person> list =
DSL.using(connection, sqldialect)
.fetch("SELECT * FROM Person");
.into(Person.class);
Spring JdbcTemplate:
JdbcTemplate template = // ...
List result = template.query("SELECT * FROM Person", rowMapper);
Cache the data you retrieve from database. It's always better than polling it, even if driver provides caching on its own level. You can always withdraw it if it's not needed anymore.
Maybe using a Map of employees by their primary key would help?
If You'd describe why You think You need to iterate the list more than once, than we'd see if there's a better algorithm there to get rid of that second interation in the first place.