I'm using jOOQ to get id which in MySQL is smallint unsigned primary key auto_increment
public List<Integer> getID() {
Factory sql = new Factory(Database.getInstance().connect(), SQLDialect.MYSQL);
return (List<Integer>) sql.select().from("users").fetch().getValues("id_users");
}
And go error
org.jooq.tools.unsigned.UShort cannot be cast to java.lang.Integer
Here they wrote that smallint unsigned should be cast to int.
Edit
Method should be
public List<UShort> getID() {
Factory sql = new Factory(Database.getInstance().connect(), SQLDialect.MYSQL);
return (List<UShort>) sql.select().from("users").fetch().getValues("id_users");
}
And in loop result should be cast to int.
You cannot cast UShort into Integer as it does not inherit that class. I guess you should use UShort.intValue() to retrieve the Integer.
The java lang cannot cast that directly. You need am intermediate step.
Something like UShortval.intValue()
Iterate the result of the query, and build up a new List where you add the result of ushortval.intValue()
If the users is a system table, thus you cannot change the type then you have to convert it to Integer. Otherwise you could change a table and provide TINYINT(4) for type Short Java.
jOOQ can do the type casting and/or conversion for you. Here are a couple of examples:
Result<?> result = sql.select().from("users").fetch();
// Without any type information
List<?> list1 = result.getValues("id_users");
// Using your implicit knowledge about id_users being an unsigned short:
#SuppressWarnings("unchecked")
List<UShort> list2 = (List<UShort>) result.getValues("id_users");
// Using jOOQ's code-generator for type-safe field access:
List<UShort> list3 = result.getValues(USERS.ID_USERS);
// Using jOOQ's conversion features to convert UShort into whatever you prefer
List<Integer> list4a = result.getValues("id_users", Integer.class);
List<Integer> list4b = result.getValues(USERS.ID_USERS, Integer.class);
The last example being what you were probably looking for.
See the relevant Javadocs here:
org.jooq.Result.getValues(Field, Class)
org.jooq.tools.Convert.convert(Object, Class)
Note that the link to the Sybase ASE manual is refering to a SQL cast operation, not a Java cast expression. That might have been what was misleading to you...
Related
I am running a simple insert query on a MySQL table with the following primary key declaration :
id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY
They key returned is a BigInteger for some reason. What changes do I need to make for a Long value to be returned as the key?
EDIT
I'm making a mini-ORM basically and the Long type is not known at compile time since it is a class parameter (AbstractDao<T, I>). Essentially I need to be able to convert a Number to a Long without using anything that has long in it (Long.valueOf(), .longValue(), etc).
I do however have a Class instance that contains Long.class :
protected Class<?> idClass = ((Class<?>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]);
Can that instance somehow be used to perform the casting? You cannot just cast a BigInteger to a Long, nor can you cast a String representation of BigInteger to a Long sadly. If there was a way to access valueOf() from my class object this might work?
executeAndReturnKey(...) returns a Number, so call longValue() if you want the result as a long.
If your method doesn't know the exact numeric type needed by the caller, let the caller do the longValue(). Alternatively, write multiple methods, for the various return types you want to support, e.g.
public Number insertAndGetKey(...) {
return ...executeAndReturnKey(...);
}
public int insertAndGetIntKey(...) {
return insertAndGetKey(...).intValue();
}
public long insertAndGetLongKey(...) {
return insertAndGetKey(...).longValue();
}
This, although extremely ugly, works like a charm :
var method = idClass.getMethod("valueOf", String.class);
var result = method.invoke(null, key.toString());
This returns something I can then typecast to (I) without issues. Please do let me know if you have a better solution to all this. The original question being about the BigInteger return type, this can probably be avoided.
I want to the set null values on runtime depending on the type I get
Here is my code
#SuppressWarnings("rawtypes")
// input can be Intger,Date, BigInt etc which Mysql supports
String input = "."+st.getType();
// param :- java.sql.Types.Integer or java.sql.Types.BigInt
Class clazz = Class.forName("java.sql.Types");
Field field = clazz.getField(input);
int val = field.getInt(null);
pstmt.setNull(1,val);
I'm going to slightly challenge your question in this answer. I do not believe that you need to do what you are doing, but as it's somewhat unclear, I'll do what I can to help you out.
First, based on the variable name pstmt I'm going to guess that this is a PreparedStatement that looks something like this:
INSERT INTO my_table (my_int, my_date, my_varchar, my_bool) VALUES (?, ?, ?, ?);
If this is the case, then you don't need to do any reflection at all, because Parameter 1 will always be an INTEGER, Parameter 2 will always be a DATE and so on. So you know what type to use in setNull because you know the position already (because you have to, because it's the first argument to setNull), and you know the statement. It's generally going to be much easier to follow your code if you just do the obvious thing and set the values.
if (myInt != null) {
pstmt.setInt(1, myInt);
} else {
pstmt.setNull(1, Types.INTEGER);
}
pstmt.setDate(2, myDate); // already handles null
// and so on
Now, this might get a tad trickier if you're trying to set the columns in a loop for some reason. I suggest to you that this is a bad idea because it'll be less obvious to future developers what you're up to.
However, the JDBC API has setObject for just such an occasion. setObject will allow null values, so you don't have to handle the null and not-null cases separately. There's even a version of setObject that will allow you to do this without specifying the type. In that case, it's just:
for (int i = 0; i < myObjects.size(); ++i) {
Object obj = myObjects.get(i);
pstmt.setObject(i, obj);
}
No casting, no remembering the type, no reflection needed. The documentation says it's not supported by every database, but I'd give this a shot before you do reflection.
Now to Answer Your Question
If, for some reason, you need to do this with reflection (because you're one of the unlucky few whose database doesn't support un-typed nulls), you were actually pretty close.
public void apply(PreparedStatement pstmt, int param, String typeName, Object value) {
try {
Class<?> types = Types.class;
Field field = types.getField(typeName);
int typeValue = field.getInt(null);
pstmt.setObject(param, obj, typeValue);
} catch (Exception e) {
// handle exceptions
}
}
So what's different here from what you were trying? First, the field name doesn't have a . in front of it. That's not part of the field name. Secondly, the typeName parameter here must exactly match the java.sql.Types field name. This is a case-sensitive String. So, for example it's "INTEGER" not "int". In your comment, you indicated that your st.getType() method had an ArrayList. I've assumed that this method returns a single string, based on its knowledge of the query. Just make sure that your type names are the same as the names used by java.sql.Types and that the object in question can actually be used as (cast / converted to) that type.
I am using reflections to map an ResultSet to a Field in bean.
field = clazz.getDeclaredField(str);
field.setAccessible(true);
Object resultSetObject = rs.getObject(str);
Class fieldType = field.getType();
field.set(clazzInst, fieldType.cast(resultSetObject));
The problem is resultSetObject is of type Integer and fieldType is of Long and I cannot cast Intger to Long and getting ClassCastException.
You are essentially asking to duplicate the type knowledge that is available at compile-time with which the compiler generates the correct conversion. The runtime doesn't have this knowledge, so you will have to provide it by building a matrix of types and coding all the conversions you want, explicitly.
You can define this as a matrix indexed by type along both axes (from-type and to-type) or more likely as a Map whose key is a ConversionType object each instance of which defines fromType, toType and a convert() method.
Whether you have
Object ref = new String("object of type string");
or
String ref = new String("still object of type string");
the object referenced will be of type String. Doing
Object obj = (Object) new String("still a string");
does not change that the referenced object is a String. In your case, you'll probably need a conversion strategy to convert between types.
You still have another option, convert long to string ,and then convert to integer.
How do I save an Integer type (not int) into Database?
Using plain JDBC, I'd use the following:
Integer myInteger = ...;
PreparedStatement ps = ...;
if (myInteger == null) {
ps.setNull(1, Types.INTEGER);
} else {
ps.setInt(1, myInteger); // will be autounboxed
}
I think just use Integer is OK.Or use intValue() to convert it.
http://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html#setInt(int, int)
Depending on your database system (mysql, postgre, ...), the integer type will or won't exist in your database. It is then better to use java Integer functions to make an Integer from your database value, which will probably be int or even bigint, depending on what's needed.
As I said in my comment, something like Integer myinteger = new Integer(yourdatabasevalue) should work fine.
I am using reflection in java.
I am getting to know the type of method parameter I am passing at run time. So I am fetching the parameter value from file into a string variable.
SO now if i get to know that the parameter type as integer and if i pass an object containting the string value I am getting
argument type mismatch
java.lang.IllegalArgumentException: argument type mismatch
Class classDefinition = Class.forName("webservices."+objectName);
String methodName = set"+fieldNameAttay[i].substring(0,1)).toUpperCase()+fieldNameAttay[i].substring(1); Field f = classDefinition.getDeclaredField(fieldNameAttay[i]);
try
{
//argType = f.getType();
Method meth = classDefinition.getMethod(methodName,f.getType());
Object arg = new Object[]{fieldValueArray[i]}; //fieldValueArray[i] is always string array
meth.invoke(object, arg); //If f.getType is Integer this //throws ex
}
catch (Exception e)
{
System.err.println(e.getMessage());
e.printStackTrace();
}
You can't cast a string to an integer - you can parse it though. For example:
if (parameterType == int.class && argumentType == String.class)
{
int integerArgument = Integer.parseInt((String) argumentValue);
// Now call the method appropriately
}
Of course, you also need to consider Integer as well as int.
How about
Integer.parseInt((String) stringObj)
Note that casting can happen only if the two objects belong in the same hierarchy. So this is not casting.
If the only types you are using are String and Integer, checking the type and then using Integer.parseInt might be the simplest thing to do.
However if you have more different types, I would suggest checking out the good old JavaBeans framwork: http://download.oracle.com/javase/tutorial/javabeans/index.html
And especially the PropertyEditors
http://download.oracle.com/javase/7/docs/api/java/beans/PropertyEditor.html
http://download.oracle.com/javase/7/docs/api/java/beans/PropertyEditorManager.html
The PropertyEditors allow you to set the value as text, and then retrieve the value as correct type. Assuming you have implemented and registered the property editors, the steps to get the correct type are similer to this:
Find out the type of the parameter
Retrieve a PropertyEditor for that type
Use setAsText and getValue in the property editor to convert the value to correct type
...or You can just adapt the same mechanism to your simple needs by implementing your own conversion framework with similar but simpler interfaces.
System.out.println(Integer.parseInt(obj.toString()))
There's another way to do it:
Integer number = Integer.valueOf("1");