Resultset relative skips last record in Java/Access - java

My Database :
+---------+-----------+---------------+-------------------+---------------+-----------------+--------------------+
| KlantId | KlantNaam | KlantVoornaam | KlantAdres | KlantPostcode | KlantWoonplaats | KlantGeboorteDatum |
+---------+-----------+---------------+-------------------+---------------+-----------------+--------------------+
| 1 | Vervoort | Dieter | Grootstraat 1 | 3500 | Hasselt | 1/01/1991 |
| 2 | Droogmans | Jos | Kleine Laan 2 | 3500 | Hasselt | 5/05/1999 |
| 3 | Severijns | Sarah | Brede Weg 3 | 3570 | Alken | 28/02/1972 |
| 4 | Peeters | Piet | Rondplein 4 | 3600 | Genk | 6/08/1973 |
| 5 | Vreemans | Veerle | Lange Boulevard 5 | 3500 | Hasselt | 4/04/1980 |
+---------+-----------+---------------+-------------------+---------------+-----------------+--------------------+
My code where I read it :
try {
System.out.println("De klanten zijn:");
if (!rs.relative(1)) {
rs.first();
}
System.out.println("Naam en voornaam: " + rs.getString("KlantVoornaam") + " " + rs.getString("KlantNaam"));
ShowMenu();
con.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}
For some odd reason rs.relative(1) returns false on the 4th record ("Peeters Piet") while there is still one left ("Vreemans Veerle") and so it returns to the first record.
Is this a mistake in rs.relative() or in my code?
I know that I could do this with
if (!rs.next()) {
rs.first();
}
But I'm wondering why rs.relative(1) doesn't do the same job.

API documentation explicity says:
Note: Calling the method relative(1) is identical to calling the
method next() and calling the method relative(-1) is identical to
calling the method previous().
So I don't think it should be any difference. Try to debug it, or just add getRow() values in a System.out.println before calling relative(1) to check in which line you are.
EDIT: Looking your code I cannot figure out why is failing, but be aware that ShowMenu should not be called by the rest of the methods: you are chaining calls in the stack.It's very hard to produce it manually, but enough user interactions could crash the application. A better way to do that is having a loop in showMenu(), which would be broken when user press 5.
SOLUTION: You're right, the issue is the mySQL implementation of ResultSet. Check this API doc, where mySQL code says EXACTLY THE OPPOSITE as we expected (Current version of the driver renamed this class to com.mysql.jdbc.ResultSetImpl, but the comment remains there):
Note: Calling relative(1) is different than calling next() since is
makes sense to call next() when there is no current row, for example,
when the cursor is positioned before the first row or after the last
row of the result set.
And method names should start with lowercase (following Java conventions makes code more readable for others ;) )

Related

Java - building a new members block

I am new to Java Spring Boot and I am looking to create a set of admin dashboard components.
One is a "new members" in the last 28 days block.
So the user table will look something like this
id | email | password | registeredDate
1 | a#gmail.com | $2hasdhdahjasd | 12/01/2017
2 | b#gmail.com | $2hdsfdsfhgjsd | 15/01/2017
3 | c#gmail.com | $4sdfdggfdsfsd | 17/01/2017
4 | d#gmail.com | $6hasdfdahjasg | 01/02/2017
5 | e#gmail.com | $9fdfdfdahjasg | 03/02/2017
6 | f#gmail.com | $89dddfdahjasg | 07/02/2017
7 | g#gmail.com | $fghgdfdahjasg | 07/02/2017
--
so in this instance - say its February - "4+25%"
What kind of algorithms/logic do I start with to get the correct data?
// 28 days ago
Calendar thresholdPast = Calendar.getInstance();
thresholdPast.set(Calendar.HOUR_OF_DAY,0);
thresholdPast.set(Calendar.MINUTE,0);
thresholdPast.set(Calendar.SECOND,0);
thresholdPast.add(Calendar.DATE,-28);
I am using a JPA to get the data out of the system - if there is a way of creating a line that will fetch these stats?
public interface TblLoginRepository extends JpaRepository<TblLogin, String> {
long count();
List<TblLogin> findAll();
}

JAVA - Storing result set in hash table by grouping data efficiently

I'd like to store in a hash table a result set coming from a query execution.
The hash table is something like this
Map<List<String>,List<Object>>
where
List<String>, the hash table key, is a subset of the extracted fields
Object is a Java object corresponding to a database tuple (all fields)
So, first, data have to be grouped in order to create each key and group all the items sharing this key.
The pseudo-code related to my current approach is:
while(iterate){
while(rs.next){
if(key is empty)
// build REFERENCE KEY and delete rs entry
else
// build key for i-th rs entry and compare it with the REFERENCE key.
Eventually, get data and delete rs entry
}
rs.beforeFirst()
}
In other words, the result set is iterated many times and each time a new key is created, in order to compare the ramaining result set entries with it. Each time the processed entry is deleted to exit the outer loop.
Since the result set is very large (and also each List(Object) ), performance are poor (a very high loading time per key).
Appending an order by clause to the query (in order to preliminarily group data) doesn't alleviate the problem.
Is there a more efficient approach?
Thanks everyone.
EDIT
Input ResultSet
---------------------------------------------------------------
| Field1 | Field2 | Field3 | Field4 | Field5 | Field6 | Field7 |
---------------------------------------------------------------
| X | A | val1_3 | val1_4 | val1_5 | val1_6 | val1_7 |
| X | A | val2_3 | val2_4 | val2_5 | val2_6 | val2_7 |
| Y | B | val3_3 | val3_4 | val3_5 | val3_6 | val3_7 |
| Z | C | val4_3 | val4_4 | val4_5 | val4_6 | val4_7 |
| Y | D | val5_3 | val5_4 | val5_5 | val5_6 | val5_7 |
----------------------------------------------------------------
Key_Fields : [Field1, Field2]
Output Map
-----------------------------------
| KEY | VALUE |
-----------------------------------
| [X,A] | [Object1, Object2] |
| [Y,B] | [Object3] |
| [Z,C] | [Object4] |
| [Y,D] | [Object5] |
-----------------------------------
I'm using List<String> for key because another ResultSet can have a Key_Fields of different lenght.
Here, my current time-consuming Java code
while(itera){
key = new ArrayList<String>();
values = new ArrayList<AbstractClass>();
while(rs.next()){
if(key.isEmpty()){
// build REFERENCE KEY
// add first OBJECT to List<AbstractClass>
// delete this data from ResultSet
}
else{
// Build KEY_TO_BE_COMPARED
List<String> row_to_be_compared = new ArrayList<String>();
// If this key equals to REFERENCE KEY
if(row_to_be_compared.equals(key)){
AbstractClass value_object = new AbstractClass();
...
rs.deleteRow();
}
// ORDERBY clause in query ensures that, if keys don't match, then all objects related to REFERENCE KEY have been collected
else{
break;
}
}
}
rs.beforeFirst();
map.put(key, values);
if(!rs.next() || items_loaded==max_hash_size)
itera = false;
else
rs.beforeFirst();
}
}
Instead of using List as key. Use a class having List as its instance variable. Override equals very carefully.
Why don't you simplify your key and make it a String that contains all the concatenated fields concatenated by a special character (say .)?

Spark - sample() function duplicating data?

I want to randomly select a subset of my data and then limit it to 200 entries. But after using the sample() function, I'm getting duplicate rows, and I don't know why. Let me show you:
DataFrame df= sqlContext.sql("SELECT * " +
" FROM temptable" +
" WHERE conditions");
DataFrame df1 = df.select(df.col("col1"))
.where(df.col("col1").isNotNull())
.distinct()
.orderBy(df.col("col1"));
df.show();
System.out.println(df.count());
Up until now, everything is OK. I get the output:
+-----------+
|col1 |
+-----------+
| 10016|
| 10022|
| 100281|
| 10032|
| 100427|
| 100445|
| 10049|
| 10070|
| 10076|
| 10079|
| 10081|
| 10082|
| 100884|
| 10092|
| 10099|
| 10102|
| 10103|
| 101039|
| 101134|
| 101187|
+-----------+
only showing top 20 rows
10512
with 10512 records without duplicates. AND THEN!
df = df.sample(true, 0.5).limit(200);
df.show();
System.out.println(users.count());
This returns 200 rows full of duplicates:
+-----------+
|col1 |
+-----------+
| 10022|
| 100445|
| 100445|
| 10049|
| 10079|
| 10079|
| 10081|
| 10081|
| 10082|
| 10092|
| 10102|
| 10102|
| 101039|
| 101134|
| 101134|
| 101134|
| 101345|
| 101345|
| 10140|
| 10141|
+-----------+
only showing top 20 rows
200
Can anyone tell me why? This is driving me crazy. Thank you!
You explicitly ask for a sample with replacement so there is nothing unexpected about getting duplicates:
public Dataset<T> sample(boolean withReplacement, double fraction)

How do I map a resultset to a nested structure of objects?

I have a result set like this…
+--------------+--------------+----------+--------+
| LocationCode | MaterialCode | ItemCode | Vendor |
+--------------+--------------+----------+--------+
| 1 | 11 | 111 | 1111 |
| 1 | 11 | 111 | 1112 |
| 1 | 11 | 112 | 1121 |
| 1 | 12 | 121 | 1211 |
+--------------+--------------+----------+--------+
And so on for LocationCode 2,3,4 etc. I need an object (to be converted to json, eventually) as : List<Location>
Where the the hierarchy of nested objects in Location Class are..
Location.class
LocationCode
List<Material>
Material.class
MaterialCode
List<Item>
Item.class
ItemCode
Vendor
This corresponds to the resultset, where 1 location has 2 materials, 1 material(11) has 2 Items, 1 item(111) has 2 vendors. How do i achieve this? I have used AliasToBeanResultTransformer before, but i doubt it will be of help in this case.
I don't think there is a neat way to do that mapping. I'd just do it with nested loops, and custom logic to decide when to when to start building the next Location, Material, Item, whatever.
Something like this pseudo-code:
while (row = resultSet.next()) {
if (row.locationCode != currentLocation.locationCode) {
currentLocation = new Location(row.locationCode)
list.add(currentLocation)
currentMaterial = null
} else if (currentMaterial == null ||
row.materialCode != currentMaterial.materialCode) {
currentMaterial = new Material(row.materialCode)
currentLocation.add(currentMaterial)
} else {
currentMaterial.add(new Item(row.itemCode, row.vendorCode))
}
}

List the child nodes in tree when parent expanded

I have a problem in implementing the tree structure of OID. when I click the parent , i need to display only child details, not the sub child of a child.
i.e., i need not display an OID which contains a "." (dot).
For example, if my OID structure is private.MIB.sample.first
private.MIB.sample.second and so on.
when I click on MIB, it should display only "sample" not first and second.
first and second is to be displayed when I click sample.
How can I implement this in java.
My datyabase is MySQL. The code which I tried is given below
FilteredRowSet rs = new FilteredRowSetImpl();
// for Other Types Like OBJECT-TYPE, Object_IDENTIFIER
rs = new FilteredRowSetImpl();
rs.setCommand("Select * from MIBNODEDETAILS where " + "mn_OID like '" + OID
+ ".%' order by mn_NodeType, mn_OID");
rs.setUrl(Constants.DB_CONNECTION_URL);
rs.setFilter(new MibRowFilter(1, expString));
rs.execute();
rs.absolute(1);
rs.beforeFirst();
I guess the change is to be made in the setCommand argument.
How can I do this?
Structure of mobnodedetails table
+--------------------+-------------------+-------------+
| mn_OID | mn_name | mn_nodetype |
+--------------------+-------------------+-------------+
| 1 | iso | 0 |
| 1.3 | org | 1 |
| 1.3.6 | dod | 1 |
| 1.3.6.1 | internet | 1 |
| 1.3.6.1.1 | directory | 1 |
| 1.3.6.1.2 | mgmt | 1 |
| 1.3.6.1.2.1 | mib-2 | 0 |
| 1.3.6.1.2.1.1 | system | 1 |
| 1.3.6.1.2.1.10 | transmission | 1 |
You can use something like
SELECT *
FROM mibnodedetails
WHERE mn_oid LIKE "+mn_OID+"%
AND LENGTH ("+mn_OID+") + 2 = LENGTH (mn_oid)
ORDER BY mn_nodetype, mn_oid
So if you pass mm_OID as 1.3.6.1 (|1.3.6.1 |internet |1 |)
You will get following result:
| 1.3.6.1.1 | directory | 1 |
| 1.3.6.1.2 | mgmt | 1 |
Working Demo
PS: This will not work for child more than 9 as we are using length + 2
The function given below dispalys the tree as required.
public void populateMibValues()
{
final DefaultTreeModel model = (DefaultTreeModel) this.m_mibTree.getModel();
model.setRoot(null);
this.rootNode.removeAllChildren();
final String query_MibNodeDetailsSelect = "Select * from MIBNODEDETAILS where LENGTH(mn_oid)<=9 "
+ " and mn_OID<='1.3.6.1.4.1' order by mn_OID"; // only
this.innerNodeNames.clear();
this.innerNodes.clear();
this.innerNodesOid = null;
try {
final ResultSet deviceRS = Application.getDBHandler().executeQuery(query_MibNodeDetailsSelect, null);// inner
// nodes
while (deviceRS.next()) {
final mibNode mb = new mibNode(deviceRS.getString("mn_OID").toString(), deviceRS.getString("mn_name")
.toString());
mb.m_Type = Integer.parseInt(deviceRS.getString("mn_nodetype").toString());
createMibTree(mb);
}
}
catch (final Exception e) {
Application.showErrorInConsole(e);
NmsLogger.writeErrorLog("ERROR creating MIB tree failed", e.toString());
}

Categories

Resources