I want to insert CLOB value into my Oracle database and here is the what I could do. I got this exception while inserting operation "ORA-01461: can bind a LONG value only for insert into a LONG column". Would someone able to tell me what should I do? Thanks.
List<Object> listObjects = dao.selectAll("TABLE NAME", new XRowMapper());
String queryX = "INSERT INTO X (A,B,C,D,E,F) VALUES (?,?,?,?,?,XMLTYPE(?))";
OracleLobHandler lobHandler = new OracleLobHandler();
for(Object myObject : listObjects) {
dao.create(queryX, new Object[]{
((X)myObject).getA(),
((X)myObject).getB(),
new SqlLobValue (((X)myObject).getC(), lobHandler),
((X)myObject).getD(),
((X)myObject).getE(),
((X)myObject).getF()
},
new int[] {Types.VARCHAR,Types.VARCHAR,Types.CLOB,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR});
}
Are your parameters in the correct order? It's like the SQL statement has the LOB as the 6th parameter, but you're setting the LOB as the 3rd parameter.
Also, I assume getA() to getF() all return String values?
The first thing I'd do is eliminate either column C or F from your insert to determine which one is causing the error.
Related
I am using below bean definition to configure a reader to read some data from the database table in a Spring Batch project. It is using a named param in SQL. I am passing A java.util.List as a parameter. However, I am getting Invalid Column type error when it tries to run the SQL.
If I just hard code one single value (namedParameters.put("keys", "138219"); ) instead of passing a list, it works.
#Bean
public JdbcCursorItemReader<MyDTO> myReader() {
JdbcCursorItemReader<MyDTO> itemReader = new JdbcCursorItemReader<>();
itemReader.setDataSource(myDatasource);
itemReader.setRowMapper(return new RowMapper<MyDTO>() {
#Override
public MyDTO mapRow(ResultSet resultSet, int rowNum) throws SQLException {
return toMyDto(resultSet);
}
};);
Map<String, Object> namedParameters = new HashMap<>();
List<Long> keys= //Some List
Map<String, List<Long>> singletonMap = Collections.singletonMap("keys", keys);
namedParameters.putAll(singletonMap);
itemReader.setSql(NamedParameterUtils.substituteNamedParameters("SELECT A FROM MYTABLE WHERE KEY IN (:keys)",new MapSqlParameterSource(namedParameters)));
ListPreparedStatementSetter listPreparedStatementSetter = new ListPreparedStatementSetter();
listPreparedStatementSetter.setParameters(
Arrays.asList(NamedParameterUtils.buildValueArray("SELECT A FROM MYTABLE WHERE KEY IN (:keys)", namedParameters)));
itemReader.setPreparedStatementSetter(listPreparedStatementSetter);
return itemReader;
}
I referred sample code snippet here as a response to one of the questions asked - it is what seems to be working when we pass one value. However, my issue is with passing a list instead of one value in the param. This is where it seems to fail.
The ListPreparedStatementSetter is not aware of parameters types. If a parameter is an array or a collection, it will set it as is to the first placeholder, leaving other placeholders unset. Hence the error. In your example, if List<Long> keys = Arrays.asList(1, 2), your sql statement will be:
SELECT A FROM MYTABLE WHERE KEY IN (?, ?)
If you pass your singletonMap to the ListPreparedStatementSetter, it will set the value of keys (which is of type List) to the first placeholder and that's it. The second placeholder will still be unset and the preparation of the statement will fail.
You can flatten parameters before passing them to the ListPreparedStatementSetter and it should work fine. I added a sample with how to flatten parameters before passing them to the prepared statement setter here (See flatten method).
Hope this helps.
I have a native SQL query in Hibernate. I get the query result by :
List l = query.list().
I know that each element of the list corresponds to a line of the result table. But what are the types of those elements ?
Java tells me they are of type : Object. Ok but I want more. Because I want to print the results in the Eclipse console. But for that, I have to know the types, I have to know what this list exactly contains.
Here is the result table of my query I get in SL Developer :
And know, I want to print all that data in Eclipse console
In Eclipse, I use Query query = session.createSQlQuery("my query");
List l = query.list();`
For information, here is the SQL query code :
The Object in the list is an array of Objects (one per column).
You have to iterate (that's for each row) then use the array of columns:
final List<Object> l = query.list();
for (final Object row : l) {
final Object[] columns = (Object[]) row;
// use columns[0], columns[1] etc
System.out.println(columns[0]);
}
If I've got your issue correct, try getClass().getName() methods, which'll give you runtime class of your object. More info here
I wrote this code to set the a jTable to a model to suit the data that would be returned from my query. I am not sure why this is happening but I do have an example of the same code in use and it works perfectly.
Note: the query calls records from a table that is linked to another table.
Note: Some may say this is a duplicate question but I feel not becuase Ilooked at that question and non of the solutions helped me, I tried using the iterator instead but same error occurs.
Any suggestions.
This is the code
public void createModelsAndEquipmentTableModel(){
Query query = FinancialDBPUEntityManager.createQuery("SELECT t FROM Stocktbl t WHERE t.chemical = FALSE");
List<Object[]> results = query.getResultList();
String headings[] = {"Product ID", "Product Name", "Number In Stock", "Number Needs Replacing"};
Object data[][] = new Object[results.size()][headings.length];
int index = 0;
for(Object[] obj: results){// error occurs here.
data[index++] = obj;
}
DefaultTableModel model = new DefaultTableModel(data, headings);
tblquipment.setModel(model);
}
This is the Relevant portion of the stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: GUIPac.Stocktbl cannot be cast to [Ljava.lang.Object;
at GUIPac.ViewStockInfo.createChemicalsTableModel(ViewStockInfo.java:53)
at GUIPac.ViewStockInfo.<init>(ViewStockInfo.java:30)
The query "SELECT t FROM Stocktbl t WHERE t.chemical = FALSE" will return Stocktbl objects.
When iterating over the ResultList this causes ClassCastExceptions.
I would recommend to use this createQuery-Method:
TypedQuery<Stocktbl> query = FinancialDBPUEntityManager.createQuery("SELECT t FROM Stocktbl t WHERE t.chemical = FALSE", Stocktbl.class);
and then resolve all compiler warnings and errors.
If you need an Object Array, you will have to produce it manually, when using JPA. Here is a pseudo-code for creating these Object Arrays:
for(Stocktbl stock : results){// no error occurs here anymore.
Object[] obj = new Object[] {stock.ProductId, stock.ProductName, stock.NumberInStock, stock.numberNeedsReplacing};
data[index++] = obj;
}
please change field names of Stocktbl stock to fit to your Stocktbl class
The getResultList()- method get back a List of List<Stocktbl> not of Object[].
In runtime there is no generic. But when you iterate over it the cast fails.
I need to fetch the result of the following query but i am getting a typecast exception. Kindly help out!
SELECT COUNT(*) FROM ( SELECT DISTINCT a.PROPSTAT_CODE,a.PROPSTAT_DESC,a.PROPSTAT_TYPE FROM CNFGTR_PROPSTAT_MSTR a WHERE 1 = 1 )
My code is given below,
Query query = session.createSQLQuery(sqlQuery);
listRes = query.list();
int ans = ((Integer)listRes.get(0)).intValue();
Thanks in advance
Since you say that you are wrapping the above query in another query that returns the count, then this will give you want, without having to convert to any other data types.
Integer count = (Integer) session.createSQLQuery("select count(*) as num_results from (SELECT DISTINCT a.PROPSTAT_CODE,a.PROPSTAT_DESC,a.PROPSTAT_TYPE FROM CNFGTR_PROPSTAT_MSTR a WHERE 1 = 1)")
.addScalar("num_results", new IntegerType())
.uniqueResult();
System.err.println(count);
The trick is the call to "addScalar". This tells Hibernate you want the data type of "num_results" pre-converted to an Integer, regardless of what your specific DB implementation or JDBC driver prefers. Without this, Hibernate will use the type preferred by the JDBC driver, which explains why different answers here have different casts. Setting the desired result type specifically removes all guesswork about your returned data type, gives you the correct results, and has the added bonus of being more portable, should you ever wish to run your application against a different relational database. If you make the call to "list" instead of "uniqueResult" then you can assign the results directly to a List
Use long instead of int. Hibernate returns count(*) as long not int.
Query query = session.createSQLQuery(sqlQuery);
listRes = query.list();
long ans = (long)listRes.get(0);
Well.. I suppose this should work:
Query query = session.createSQLQuery(sqlQuery);
List listRes = query.list();
int ans = ((BigDecimal) listRes.get(0)).intValue();
Note: you need to import java.math.BigDecimal
List number=session.createSQLQuery("SELECT COUNT(*) FROM devicemaster WHERE ClientId="+id).list();
session.getTransaction().commit();
int ans = ((java.math.BigInteger) number.get(0)).intValue();
I have a Hibernate managed Java entity called X and a native SQL function (myfunc) that I call from a Hibernate SQL query along these lines:
SQLQuery q = hibernateSession.createSQLQuery(
"SELECT *, myfunc(:param) as result from X_table_name"
);
What I want to do is to map the everything returned from this query to a class (not necessarily managed by Hibernate) called Y. Y should contain all properties/fields from X plus the result returned by myfunc, e.g. Y could extend class X and add a "result" field.
What I've tried:
I've tried using q.addEntity(Y.class) but this fails with:
org.hibernate.MappingException: Unknown entity com.mycompany.Y
q.setResultTransformer(Transformers.aliasToBean(Y.class)); but this fails with: org.hibernate.PropertyNotFoundException: Could not find setter for some_property. X has a field called someProperty with the appropriate getter and setter but in this case it doesn't seem like Hibernate maps the column name (some_property) to the correct field name.
q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); returns a Map but the values are not always of the type expected by the corresponding field in X. For example fields in X of type enum and Date cannot be mapped directly from the Map returned by the SQL query (where they are Strings).
What's the appropriate way to deal with this situation?
See the chapter of the documentation about SQL queries.
You can use the addScalar() method to specify which type Hibernat should use for a given column.
And you can use aliases to map the results with the bean properties:
select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t
Or, (and although it require some lines of code, it's my preferred solution), you can simply do the mapping yourself:
List<Object[]> rows = query.list();
for (Object[] row : rows) {
Foo foo = new Foo((Long) row[0], (String) row[1], ...);
}
This avoids reflection, and lets you control everything.
Easy. Cast the rows to Map<String, Object>:
final org.hibernate.Query q = session.createSQLQuery(sql);
q.setParameter("geo", geo);
q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
final List<Map<String, Object>> src = q.list();
final List<VideoEntry> results = new ArrayList<VideoEntry>(src.size());
for (final Map<String, Object> map:src) {
final VideoEntry entry = new VideoEntry();
BeanUtils.populate(entry, map);
results.add(entry);
}
First of all you need to declare the entity in the hibernate configuration xml file something like this: .....
class="path to your entity"
Or you can do the same thing programatically before you make the query.