From: Lew on
harryajh wrote:
>>> ResultSet rs = ps.executeQuery();
>>>
>>> while (true)
>>> {
>>> ret = new myBean();
>

Class names should start with an upper-case letter.

>>> String propName = rs.getString(2);
>>>
>>> if (propName.equalsIgnoreCase("licence_number"))
>>> {
>>> ret.setLicenceNo(rs.getString(3));
>>> }
>>> else if (propName.equalsIgnoreCase("return_requirement_id"))
>>> {
>>> ret.setReturnReqId(rs.getString(3));
>>> }
>>> }
>

It looks like you might need to revise your database query or schema -
the same column of the result should not mean different things.

But since it does ...

Alan Gutierrez wrote:
> I read the OPs uncompilable code as being a loop over a result set, even
> though it has that nonsense while(true) which really should read while
> (rs.next()), but then maybe the OP really wants an infinite loop over a
> single row of a result set. In which case, it doesn't matter how much
> faster it runs.
>

One way would be to have an enum keyed to the different possible
values from column 2 with a service method to set the correct value
from column 3, something similar to this uncompiled (let alone tested)
idea:

public enum ColumnSetter
{
licence_number
{
@Override
public void setColumn3( MyBean ret, String value )
{
ret.setLicenceNo( value );
}
},
return_requirement_id
{
@Override
public void setColumn3( MyBean ret, String value )
{
ret.setReturnReqId( value );
}
};
abstract public void setColumn3( MyBean ret, String value );
}

Then the client code is something along the uncompiled, untested lines
of:

...
PreparedStatement ps = Connection.prepareStatement( ... );
try
{
// set up query parms
MyBean ret = new MyBean();
for( ResultSet rs = ps.executeQuery(); rs.next(); )
{
ColumnSetter cs = ColumnSetter.valueOf( rs.getString( 2 ));
cs.setColumn3( ret, rs.getString( 3 )); // risks NPE
}
return ret;
}
finally
{
ps.close();
}

You can create a replacement method in ColumnSetter for valueOf() that
is case-insensitive. I usually define an instance override
'toString()' and static 'fromString()' for enums.

(As a riff on "RAII" I call the above try...finally idiom variously
"RRIG" or "RRIF" or "RRID", respectively "Resource Release is
Guaranteed", "Resource Release in Finally" or "Resource Release in
Deallocation". Your votes welcomed.)

--
Lew
From: Andreas Leitgeb on
harryajh <harryreg_uk(a)yahoo.co.uk> wrote:
> if (propName.equalsIgnoreCase("licence_number"))
> else if (propName.equalsIgnoreCase("return_requirement_id"))

One thing to avoid unnecessary waste might be to "toLowerCase()" once,
and then use plain .equals() for comparisons.

Next step would be to look up the toLowerCase()'d property name in
a HashMap, that has all 10 strings associated with a small integer,
which you then use in a switch(...){...} to get the appropriate
method called on the MyBean for each number.


The "OO" way, would be to have some interface like
interface Storer { void store(MyBean b,String s); }
and in the HashMap you associate anonymous Storer-implementations:
Map<String,Storer> m = new HashMap<String,Storer>();
m.put("licence_number",new Storer() {
public void store(MyBean b,String s) { b.setLicenceNo(s); } } );
m.put("return_requirement_id",new Storer() {
public void store(MyBean b,String s) { b.ret.setReturnReqId(s); } } );
// ... ditto for the further 8 mappings

MyBean b = new MyBean();

Then, inside the loop:
m.get(rs.getString(2).toLowerCase()).store(b,rs.getString(3));

Well, actually you may want to break this up into separate statements
storing intermediate results in local variables and do null-checks
where appropriate.

For best encapsulation, you could add a method to MyBean, that takes
the Property's name and new value, and does the HashMap-lookup and
invocation of the obtained Storer. The HashMap itself would also be
maintained by MyBean and created and populated in the static initializer,
or lazily on first use.

I do not claim, that any of these would actually make your whole program
faster, but I dislike those if-chains, anyway, so even if your program
doesn't end up faster, I think those alternatives would still be worth
considering.

PS: "myBean" was a bad class-name and "GetString" is not a method of
ResultSet, so I changed them.
From: Jim Janney on
Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> writes:

> harryajh <harryreg_uk(a)yahoo.co.uk> wrote:
>> if (propName.equalsIgnoreCase("licence_number"))
>> else if (propName.equalsIgnoreCase("return_requirement_id"))
>
> One thing to avoid unnecessary waste might be to "toLowerCase()" once,
> and then use plain .equals() for comparisons.

It depends. If you look at the code for String.equalsIgnoreCase, it
doesn't have that much overhead compared to .equals. If there are 10
choices that are all equally likely, each iteration of the loop will
average 5 comparisons, so you're balancing the extra cost of 5
case-insensitive comparisons against the possibility of creating a new
object. Note that equals or equalsIgnoreCase often return false
immediately after comparing lengths.

If the choices are *not* all equally likely, you can cut down on the
average number of comparisons by testing for the most common values
first.

--
Jim Janney
From: Jim Janney on
harryajh <harryreg_uk(a)yahoo.co.uk> writes:

> I have to process a large number of database records, examine a column
> value (can be 10 different values) and set a bean's property depending
> on that fields values e.g (vastly cut down)
>
> ResultSet rs = ps.executeQuery();
>
> while (true)
> {
> ret = new myBean();
>
> String propName = rs.getString(2);
>
> if (propName.equalsIgnoreCase("licence_number"))
> {
> ret.setLicenceNo(rs.getString(3));
> }
> else if (propName.equalsIgnoreCase("return_requirement_id"))
> {
> ret.setReturnReqId(rs.getString(3));
> }
> }
>
> Hopefully its relativily easy to follow what I'm trying to do, my big
> problem though is using a "String" to hold the fields value, this
> obviously is not a good idea and surely for performance reasons
> neither would -
>
> if (rs.getString(2).equalsIgnoreCase("licence_number"))
>
> or wouldn't it make much difference getting the field value up to 10
> times?
>
> A bit lost as to what's the best/efficient way to do this, should I
> use a StringBuffer every time? would it be garbage collected? - any
> other ideas?
>
> thanks

Your first mistake is thinking that anything you do here will have a
measurable effect on performance. It won't: the run time will always
be dominated by the call to ps.executeQuery().

However, there's another mistake that I can't bring myself to ignore,
so: no, using a String to hold the field's value is not wrong, and
using a StringBuilder will not help you.

--
Jim Janney

From: Lew on
harryajh writes:
>> A bit lost as to what's the best/efficient way to do this, should I
>> use a StringBuffer every time? would it be garbage collected? - any
>> other ideas?

Jim Janney wrote:
> However, there's another mistake that I can't bring myself to ignore,
> so: no, using a String to hold the field's value is not wrong, and
> using a StringBuilder will not help you.

It's even worse than that. He asked about using a StringBuffer.

--
Lew