I have a method that compares the value of objects (as string, date, number...) and returns true or false depending of the result.
I've created a unit test for this method, but I'm having a problem testing the clob comparison, because with JUnit I don't have a connection, and if I use SerialClob to create two clobs (with the same content), I get objects with the same reference (so the part that compare clobs is not tested), I don't understand why two "new" generate the same object reference?
And another thing I don't understand, if I compare a string with a clob (identical values), the code that compares the clob is used, whereas instanceof is not supposed to be identical...!
What I expect is: when I compare 2 differents clobs, comparison as objects is false, as string (toString output) is false, it detects that objects are instanceof clobs, so convert them as string, and then compare string values.
Here is my code (simplified for example):
import java.io.*;
import java.sql.*;
import javax.sql.rowset.serial.*;
public class TestClob {
public static void main(String[] args) throws SerialException, SQLException {
boolean result;
Object text1="abcdef", text2="abcdef";
Clob clob1 = new SerialClob(((String) text1).toCharArray());
Clob clob2 = new SerialClob(((String) text2).toCharArray());
Clob clob3 = new SerialClob("abcdefg".toCharArray());
System.out.println("TEST 1, basic string comparison");
System.out.println("-------------------------------");
result = haveSameValue(text1, text2);
System.out.println("result: "+result);
System.out.println("\nTEST 2, clob vs string");
System.out.println("----------------------");
result = haveSameValue(clob1, text1);
System.out.println("result: "+result);
System.out.println("\nTEST 3, different clobs objects but same value");
System.out.println("----------------------------------------------");
result = haveSameValue(clob1, clob2);
System.out.println("result: "+result);
System.out.println("\nTEST 4, different clobs");
System.out.println("-----------------------");
result = haveSameValue(clob1, clob3);
System.out.println("result: "+result);
}
public static boolean haveSameValue(Object obj1, Object obj2) {
String sObj1, sObj2, sObj1Class, sObj2Class;
boolean result = false;
if (obj1!=null && obj2!=null) {
sObj1Class = obj1.getClass().toString().toLowerCase();
sObj2Class = obj2.getClass().toString().toLowerCase();
System.out.println(" Objects class : sObj1Class="+sObj1Class+", sObj2Class="+sObj2Class);
System.out.println(" OBJECT : obj1="+obj1+", obj2="+obj2+", => equal as object? "+obj1.equals(obj2));
if (!obj1.equals(obj2)) {
sObj1=obj1.toString();
sObj2=obj2.toString();
System.out.println(" STRING : sObj1="+sObj1+", sObj2="+sObj2+", => equal as string? "+sObj1.equals(sObj2));
if (!sObj1.equals(sObj2)) {
if (obj1 instanceof java.sql.Clob || obj2 instanceof java.sql.Clob) {
sObj1 = ClobToString(obj1);
sObj2 = ClobToString(obj2);
System.out.println(" CLOB : sObj1="+sObj1+", sObj2="+sObj2+" => equal as clob? "+sObj1.equals(sObj2));
result = sObj1.equals(sObj2);
}
// other comparisons (as a date, timestamp, number...)
}
}
}
return result;
}
public static String ClobToString(Object object) {
if (object==null) {
return null;
}
else if (object instanceof java.sql.Clob) {
StringBuilder sb = new StringBuilder();
try {
Reader reader = ((java.sql.Clob) object).getCharacterStream();
BufferedReader br = new BufferedReader(reader);
String line;
while(null != (line = br.readLine())) {
sb.append(line);
}
br.close();
return sb.toString();
}
catch (Exception e) {
System.out.println("error : "+e.getMessage());
return object.toString();
}
}
else {
return object.toString();
}
}
}
and here is the output:
TEST 1, basic string comparison
-------------------------------
Objects class : sObj1Class=class java.lang.string, sObj2Class=class java.lang.string
OBJECT : obj1=abcdef, obj2=abcdef, => equal as object? true
result: true
TEST 2, clob vs string
----------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class java.lang.string
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=abcdef, => equal as object? false
STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=abcdef, => equal as string? false
CLOB : sObj1=abcdef, sObj2=abcdef => equal as clob? true
result: true
TEST 3, different clobs objects but same value
----------------------------------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@df59efc3, => equal as object? true
result: true
TEST 4, different clobs
-----------------------
Objects class : sObj1Class=class javax.sql.rowset.serial.serialclob, sObj2Class=class javax.sql.rowset.serial.serialclob
OBJECT : obj1=javax.sql.rowset.serial.SerialClob@df59efc3, obj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as object? false
STRING : sObj1=javax.sql.rowset.serial.SerialClob@df59efc3, sObj2=javax.sql.rowset.serial.SerialClob@bd7d1c2, => equal as string? false
CLOB : sObj1=abcdef, sObj2=abcdefg => equal as clob? false
result: false
boolean result = true;
should start withfalse
as the "default" result of comparing objects. As of now, based on your current code, calling the methodhaveSameValue(null, "abc");
will returntrue
saying that they have the same value (but one argument isnull
).