Oracle JDBC Resultset.getString("COLUMN_DEF") returns lower case quoted string - oracle

With oracle JDBC driver (ojdbc7.jar), when I do x=Resultset.getString("COLUMN_DEF") for a column where the default value is 'N/A' in the database ('N/A' set at table creation, 'N/A' seen with DBeaver tool) the JDBC driver return x="'n/a'" (with postgres and mysql it returns x="N/A").
do you have an idea of why it is in lower case et why it is quoted inside the result string?
thanks in advance for any kind of help on this issue!
PS: how I use the database metadata object:
private static void readColumnMetaData(AMIDBLoader dbLoader, DatabaseMetaData metaData, String internalCatalog, String externalCatalog, String _table, Map<String, String> amiEntityMap, Map<String, String> amiFieldMap) throws SQLException
{
try(ResultSet resultSet = metaData.getColumns(internalCatalog, internalCatalog, _table, "%"))
{
while(resultSet.next())
{
String table = resultSet.getString("TABLE_NAME");
String name = resultSet.getString("COLUMN_NAME");
String type = resultSet.getString("TYPE_NAME");
int size = resultSet.getInt("COLUMN_SIZE");
int digits = resultSet.getInt("DECIMAL_DIGITS");
String def = resultSet.getString("COLUMN_DEF");
code for the table creation:
CREATE TABLE "router_locations" (
"id" NUMBER(*, 0),
"continentCode" VARCHAR2(3) DEFAULT 'N/A',
"countryCode" VARCHAR2(3) DEFAULT 'N/A'
);;
Jerome

We managed to find where the string was modified and the JDBC driver is ok .. thanks for your help.

Related

spark jdbc api can't use built-in function

I want to get subquery from impala table as one dataset.
Code like this:
String subQuery = "(select to_timestamp(unix_timestamp(now())) as ts from my_table) t"
Dataset<Row> ds = spark.read().jdbc(myImpalaUrl, subQuery, prop);
But result is error:
Caused by: java.sql.SQLDataException: [Cloudera][JDBC](10140) Error converting value to Timestamp.
I can use unix_timestamp function,but to_timestmap failed, why?
I found code in org.apache.spark.sql.execution.datasources.jdbc.JDBC.compute() exists some problem:
sqlText = s"SELECT $columnList FROM ${options.table} $myWhereClause"
$columList contains " like "col_name" , when I delete " it work fine.
I solve this problem by add dialect, default dialect will add "" to column name,
JdbcDialect ImpalaDialect = new JdbcDialect(){
#Override
public boolean canHandle(String url) {
return url.startsWith("jdbc:impala") || url.contains("impala");
}
#Override
public String quoteIdentifier(String colName) {
return colName;
}
};
JdbcDialects.registerDialect(ImpalaDialect);

Query to check if the record exists in Spring Jdbc Template

I am fairly new to spring ,I am looking to check if a certain email id exists in database or not , using Spring Jdbc Template ,I looked here but could'nt find the proper answer .I am looking something like ,SELECT count(*) from table where email=?
Any help will be appreciated.
You can do something as below if you are using jdbctemplate and new version of spring
private boolean isEmailIdExists(String email) {
String sql = "SELECT count(*) FROM table WHERE email = ?";
int count = jdbcTemplate.queryForObject(sql, new Object[] { email }, Integer.class);
return count > 0;
}
queryForObject method of jdbcTemplate accepts the sql query as the first parameter, second argument is an array of objects for the sql query place holders and the third argument is the expected return value from the sql query.
In this case we only have one place holder and hence I gave the second argument as new Object[] { email } and the result we are expecting is a count which is a Integer and hence I gave it as Integer.class
I kind of got this answer from https://www.mkyong.com/spring/jdbctemplate-queryforint-is-deprecated/
You can go through it if you are interested.
private boolean isEmailIdExists(String email) {
return jdbcTemplate.queryForObject("SELECT EXISTS(SELECT FROM table WHERE email = ?)", Boolean.class, email);
}
http://www.postgresqltutorial.com/postgresql-exists/

Need DB Table name for multiple queries executed using spring JDBCTemplate

I am executing multiple queries concurrently and retrieving the results. But, the queries belong to multiple tables so, when resultset is retrieved, it is difficult to identify that a resultset belong to which table.
Can anyone help here as to how to identify the table names for each query resultset?
I tried below code but table name is blank!!!!
public static void getColumnNames(ResultSet rs) throws SQLException {
if (rs == null) {
return;
}
// get result set meta data
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
// get the column names; column indexes start from 1
for (int i = 1; i < numberOfColumns + 1; i++) {
String columnName = rsMetaData.getColumnName(i);
// Get the name of the column's table name
String tableName = rsMetaData.getTableName(i);
System.out.println("column name=" + columnName + " table=" + tableName + "");
}
}
I am calling this method like this:
jdbcTemplate.query(sql, new ResultSetExtractor<ResultSet>() {
#Override
public ResultSet extractData(ResultSet resultSet) throws SQLException,
DataAccessException {
getColumnNames(resultSet);
return resultSet;
}
});
Please advise, what is done wrong here? :(
You're not doing anything wrong here. The problem is caused by the method itself in connection with your DBMS or your JDBC driver, respectively.
See this doc please. 'table name or "" if not applicable' suggests that in your case the DBMS/driver does not provide the required information, causing the method to return an empty string.
I'm afraid, you'll have to find another way to detect which query the result originated from.

passing an object having array to oracle stored procedure

I've a class "User" as follows:
public class User{
private String firstname;
private String lastname;
private String[] departments;
}
I want to pass an object of User type to my oracle stored procedure that takes an object type as parameter. So I did this to achieve my solution:-
1. Created USER_SEARCH_OBJ as a type in database as follows:-
create or replace
TYPE USER_SEARCH_OBJ AS OBJECT (
FIRST_NAME VARCHAR2(256),
LAST_NAME VARCHAR2(256),
DEPARTMENTS TABLE_OF_VALUES,
);
2. Created TABLE_OF_VALUES as a type in database as follows:-
create or replace TYPE TABLE_OF_VALUES AS TABLE OF VARCHAR2(20);
3. Passed the User object from Java class as follows:-
Object[] departments = {"1","2"};
StructDescriptor objDescriptor = StructDescriptor.createDescriptor("USER_SEARCH_OBJ", conn.getMetaData().getConnection());
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor("TABLE_OF_VALUES", conn.getMetaData().getConnection());
ARRAY departmentArr = new ARRAY(arrayDescriptor, conn.getMetaData().getConnection(), departments );
Object[] userProperties = new Object[2];
userProperties [0] = "paras";//first_name
userProperties [1] = "anand";//last_name
userProperties [2] = departmentArr ;//department array
STRUCT searchObj = new STRUCT(objDescriptor, conn.getMetaData().getConnection(), userProperties );
CallableStatement cStmt = conn.prepareCall("PCK_SEARCH2.USER_SEARCH(?,?)");
cStmt.setObject(1, searchObj);
cStmt.registerOutParameter(2, OracleTypes.CURSOR);
cStmt.execute();
But when I run this code I get an exception as follows:-
java.sql.SQLException: Inconsistent java and sql object types
at oracle.sql.StructDescriptor.toOracleArray(StructDescriptor.java:709)
at oracle.sql.StructDescriptor.toArray(StructDescriptor.java:1296)
at oracle.sql.STRUCT.<init>(STRUCT.java:165)
at com.ensenda.lmp.web.controller.User.main(User.java:75)
This exception comes at the following line of code:-
STRUCT searchObj = new STRUCT(objDescriptor, conn.getMetaData().getConnection(), userProperties );
Please let me know where I'm going wrong.
Firstly I think you should get an ArrayOutOfBoundException because you have declared an Object[2] and trying to put a 3rd element into it. Considering that is a typo.
For the original problem instead of using setObject you can use
*JDBCUtil.setStruct(conn,cStmt,1,"USER_SEARCH_OBJ",userProperties);*

blazeds converts BigDecimal to string

I have a Flex application that uses blazeds to connect to a Java backend. Using remoting, I give a call to an API to run a SELECT statement on a table (using conventional JDBC classes) in a Oracle database.
The table has 2 columns:
PRODUCT_CODE of type NVARCHAR2(32) and
DEMAND of type NUMBER(10, 0)
My Java API is as follows:
public List<?> getQueryResult(String query) {
Connection conn = DriverManager.getConnection(connStr, userName, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
ArrayList<?> result = new ArrayList<?>();
while(rs.next()) {
Object[] itemArray = new Object[2];
itemArray[0] = rs.getObject(1);
itemArray[1] = rs.getObject(2);
result.add(itemArray);
}
return result;
}
In my Flex side, I have a handler for result event of this remote operation:
private function onResult(e:ResultEvent) : void {
var result:ArrayCollection = (e.result as ArrayCollection);
}
Strangely, the values corresponding to DEMAND column are automatically converted to string (I debugged to find out that in backend, these were BigDecimal)
Any suggestions?
Yes indeed, the BigDecimal from Java is converted to String in ActionScript, as you can read in the developer guide. There is no BigDecimal in ActionScript so it was the only option - you cannot convert any BigDecimal to int or float.
If you are sure that your value represented as NUMBER(10,0) has values in the interval -2,147,483,648 - 2,147,483,647 you can convert it to an int in java - see the code below:
itemArray[1] = ((BigDecimal)rs.getObject(2)).intValue();

Resources