Unable to understand this jdbc, ibatis error - java

I am a noob in JDBC, iBatis. I am trying to have my Java EE app execute a stored proc on a sql server but the server is throwing a weird error which does not make any sense to me. Can somebody help me understand what am I doing wrong.
This is the error:
20121221 18:42:38:960 [CONFERENCE] INFO 320 AppController - Error : Error Occurred while Speakers List data retrival: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/ABCD/conference/model/Conference.xml.
--- The error occurred while applying a parameter map.
--- Check the conference_get_speakers-InlineParameterMap.
--- Check the statement (update procedure failed).
--- Cause: com.microsoft.sqlserver.jdbc.SQLServerException: Could not find stored procedure 'imconference..conference_get_speakers'.
20121221 18:42:38:960 [CONFERENCE] INFO 323 AppController - handleException >>
Here is the mapping in the xml file:
<resultMap id="result-speakers" class="com.jpmorgan.conference.model.Attendee">
<result property="confId" column="conf_Id" />
<result property="attendeeId" column="attendee_id" />
<result property="firstName" column="first_name" />
<result property="lastName" column="last_name" />
</resultMap>
<procedure id="getSpeakers" resultMap="result-speakers">
{call
imconference..get_speakers_details(#confId#)}
</procedure>
<procedure id="conference_get_speakers" resultMap="result-speakers">
{call
imconference..conference_get_speakers(#confId#)}
</procedure>
I am able to execute the stored proc independently on the database. I guess I am making a mistake in mapping the xml file. Any help, ideas would be much appreciated. Please let me know if you guys need more information.

The general form to indicate the how to invoke your store procedure should have the following form.
{call dbname.procname(#param#}
For I can see, removing a dot from your sentences should do the magic.

Related

Hibernate slqjdbc4 column with spaces

I need to map in Java with hibernate a table in sqlserver that has spaces in the column names.
I use Sqlserver 2008 jre7 com.microsoft.sqlserver.sqljdbc4 with Hibernate 3.3.2
I found a lot of similar questions in different forums but none of the solutions I read worked.
I tried using the backtick
<property name="nameSpaces" type="string" >
<column name="`Name with spaces`" not-null="false" />
</property>
this is the error
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
I also tried to use the [] brakets but hibernate converted it in ` again.
<column name="[Name with spaces]" not-null="false" />
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
Finally I also tried both of them
<column name="`[Name with spaces]`" not-null="false" />
or
without success.
Can someone help me? Is there any hibernate configuration I can change to work with these column names.
Thanks
The answer (by BilalDja) is hidden above in a comment. I found his answer helpful so I thought I would add the answer here for others with the same problem.
This issue is hard to debug, I had to dig really deep into the hibernate and jdbc code to finally find the "real" SQL statement that is created to get data from the database. I then copied its value and ran it manually on my SQL Server database. Straight away the syntax error was obvious and sure enough it was cause by a space in a column name.
To fix this I just escaped the double quotes around the problematic column name as explained in BilalDja's comments and expanded slightly here...
#Column(name = "\"Column name\"")
private String variableColumnWillMapTo;
That's it, problem solved, no more syntax error.

AppEngine - No Indexes Serving

I have been trying to use Query.setOrdering(xxxx desc) but AppEngine gives ServerError : Unable to process the request.
Admin Console :
com.google.appengine.api.datastore.DatastoreNeedIndexException: no matching index found.
The suggested index for this query is:
<datastore-index kind="Chat_messages" ancestor="false" source="manual">
<property name="FROM_TO" direction="asc"/>
<property name="TIME" direction="desc"/>
</datastore-index>
My code in servlet :
Query q=pm.newQuery(Chat_messages.class);
q.setFilter("FROM_TO == email_emailto || FROM_TO == emailto_email");
q.declareParameters("String email_emailto,String emailto_email");
q.setRange(0, 50);
q.setOrdering("TIME desc");
With the Python runtime, the process of running the app locally with the dev server generates the index file.
Are you actually getting an error about not having the correct index? The index that you have put in your datastore-index.xml is a single property index. This means that it is automatically built by Datastore and will not show up in your console.
You can see this page which describes which queries you can perform without needing to upload any indexes.

Basic HQL statement always fails

I've recently started trying to use Hibernate, but am doing so in Netbeans. This has left me having to use this example project to try and get me up and running.
Unfortunately, at the step "Enumerating Film Titles and Retrieving Actors Using an HQL Query" my HQL queries do not give results and instead fail, with the exception:
org.hibernate.exception.SQLGrammarException: could not execute query
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from limit 100' at line 1
It seems that the HQL isn't generating proper MySQL statements but I can't seem to see why, as I've followed the example to the letter thus far.
I am attempting to connect to a local MySQL database named 'sakila', with the following details:
jdbc:mysql://localhost:3306/sakila
which seems to work correctly as I am able to browse the tables from within Netbeans no problem.
My hibernate.cfg.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.show_sql">true</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="dvdrental/Language.hbm.xml"/>
<mapping resource="dvdrental/FilmActor.hbm.xml"/>
<mapping resource="dvdrental/FilmCategory.hbm.xml"/>
<mapping resource="dvdrental/Category.hbm.xml"/>
<mapping resource="dvdrental/Film.hbm.xml"/>
<mapping resource="dvdrental/Actor.hbm.xml"/>
</session-factory>
</hibernate-configuration>
When I'm using the HQL Query window, the SQL it seems to generate only ever says 'select from ' which is obviously wrong, but I can't see why this is being caused?
Edit 1: The HQL Query tab showing my input
Completely stupid reason- I hadn't even thought about the fact I hadn't built the project, so the example code from the bottom of the example ran properly (cause it came pre-compiled). Works no problem now.
I think the main cause of the error is as stated earlier from User, the U in User should be uppercase/capitalized as hibernate uses the POJO. I tried recompiling the code and it works correctly for the sample Swing application: https://netbeans.org/kb/docs/java/hibernate-java-se.html.
However the HQL Query editor still gives this error. It is strange but seems like this editor is not reliable.
The error message 'from limit 100' from your posted exception tells me, that you forgot to add Film after from. Please provide the HQL query that throws the exception.
BTW: the examples in the example project are bad practice. You should never use inline arguments in HQL queries:
from Film as film where film.filmId between '"+startID+"' and '"+endID+"'
You should use query parameters:
Query q = session.createQuery("from Film as film where film.filmId between :startID and :endID");
q.setParameter("startID", startID);
q.setParameter("endID", endID);
When I'm using the HQL Query window, the SQL it seems to generate only ever says 'select from ' which is obviously wrong, but I can't see why this is being caused?
A simple
from Film
is valid HQL and should work. Could you try without the following line:
<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
Not sure this will solve the problem but there is no reason to use the "old" parser anyway.
That replaces the problem with a new one I'm afraid. Now the SQL tab of the HQL pane reports 'Invalid Query', and if I run the query I get org.hibernate.hql.ast.QuerySyntaxException. Any further pointers?
As I said, I was not sure this would solve the problem. What I would do is write a "simple" JUnit test to validate the setup is working. But an obvious bug like this in NetBeans HQL Query window is unlikely, IMO.
Completely stupid reason- I hadn't even thought about the fact I hadn't built the project, so the example code from the bottom of the example ran properly (cause it came pre-compiled). Works no problem now.
I experienced exactly the same problem but I think your stated solution is not correct. Even your project is not compiled HQL will show you results.
One should be careful of Table name in hibernate.cfg.xml file
as it should be same in query (case sensitive) also for example in your case it has table name as "Actor" so
from Actor will work, not from actor

Ibatis Ref Curosr issue with Oracle

I'm using Java and Ibatis to call a stored procedure on on oracle database. I seem to be having an issue setting up with parameters.
The store procedure looks like the following:
PROCEDURE Get_Semployees_By_Clt_ID
(
client_id IN HRIS.SEMPLOYEES.SEE_CLT_ID%TYPE,
ref_cursor OUT SYS_REFCURSOR
);
My Ibatis SqlMap:
<sqlMap namespace="Foo">
<resultMap id="employee-map" class="MyFoo">
<result property="foo1" column="foo1"/>
<result property="foo2" column="foo2"/>
</resultMap>
<parameterMap id="clientEmployeesParms" class="java.util.Map" >
<parameter property="in1" jdbcType="INTEGER" javaType="java.lang.Integer" mode="IN"/>
<parameter property="output1" jdbcType="ORACLECURSOR" javaType="java.sql.ResultSet" mode="OUT" />
</parameterMap>
<procedure id="clientEmployees" parameterMap="clientEmployeesParms" resultMap="employee-map">
{ call Package.Get_Clt_ID(?,?) }
</procedure>
</sqlMap>
My Java:
resource = "SqlMapConfig.xml";
reader = Resources.getResourceAsReader (resource);
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
Map map = new HashMap();
map.put("in1", new Integer(23));
list = sqlMap.queryForList("Foo.clientEmployees", map);
Error:
--- The error occurred while applying a parameter map.
--- Check the Employee.clientEmployeesParms.
--- Check the output parameters (retrieval of output parameters failed).
--- Cause: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:188)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForList(GeneralStatement.java:123)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:610)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:584)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:101)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList(SqlMapClientImpl.java:78)
at com.apache.struts.employee.model.IbatisStoredProcedure.main(IbatisStoredProcedure.java:30)
I had the exact same problem. It is produced when you have iBatis prior to 2.1.5 and log4j in the classpath.
You can find more information here:
https://issues.apache.org/jira/browse/IBATIS-152
Update to iBatis 2.1.5 or remove log4j from classpath.
I work with iBatis.NET and Oracle and the way I was able to get the refcursor back from a stored procedure is as follows (Note that the output parameter is First in the list, and the property/column match the sproc:
<parameterMap id="GetServiceTypes-param">
<parameter property="P_CURSOR" direction="Output" column="P_CURSOR" dbType="RefCursor"/>
<parameter property="P_TYPSERVICETYPE" direction="Input" />
</parameterMap>
..
PROCEDURE GETSERVICETYPES(P_CURSOR OUT CURDATA,
P_TYPSERVICETYPE CLM_SERVICE_TYPES_TBL.SERVICETYPE%TYPE := NULL);
Peter. Are you going through bootcamp? (I work where you work, possibly in the same building. I'll shoot you an email tomorrow.)
I think the problem is because the resultMap needs to have the property names be the same as what is being returned by the procedure. In this case, whatever is being selected into the cursor.

Hibernate: how to call a stored function returning a varchar?

I am trying to call a legacy stored function in an Oracle9i DB from Java using Hibernate. The function is declared like this:
create or replace FUNCTION Transferlocation_Fix (mnemonic_code IN VARCHAR2)
RETURN VARCHAR2
After several failed tries and extensive googling, I found this thread on the Hibernate forums which suggested a mapping like this:
<sql-query name="TransferLocationFix" callable="true">
<return-scalar column="retVal" type="string"/>
select Transferlocation_Fix(:mnemonic) as retVal from dual
</sql-query>
My code to execute it is
Query query = session.getNamedQuery("TransferLocationFix");
query.setParameter("mnemonic", "FC3");
String result = (String) query.uniqueResult();
and the resulting log is
DEBUG (org.hibernate.jdbc.AbstractBatcher:366) - - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG (org.hibernate.SQL:401) - - select Transferlocation_Fix(?) as retVal from dual
TRACE (org.hibernate.jdbc.AbstractBatcher:484) - - preparing statement
TRACE (org.hibernate.type.StringType:133) - - binding 'FC3' to parameter: 2
TRACE (org.hibernate.type.StringType:133) - - binding 'FC3' to parameter: 2
java.lang.NullPointerException
at oracle.jdbc.ttc7.TTCAdapter.newTTCType(TTCAdapter.java:300)
at oracle.jdbc.ttc7.TTCAdapter.createNonPlsqlTTCColumnArray(TTCAdapter.java:270)
at oracle.jdbc.ttc7.TTCAdapter.createNonPlsqlTTCDataSet(TTCAdapter.java:231)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1924)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteDescribe(TTC7Protocol.java:850)
at oracle.jdbc.driver.OracleStatement.doExecuteQuery(OracleStatement.java:2599)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2963)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:658)
at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:736)
at com.mchange.v2.c3p0.impl.NewProxyCallableStatement.execute(NewProxyCallableStatement.java:3044)
at org.hibernate.dialect.Oracle8iDialect.getResultSet(Oracle8iDialect.java:379)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:193)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1784)
at org.hibernate.loader.Loader.doQuery(Loader.java:674)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152)
at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:811)
at com.my.project.SomeClass.method(SomeClass.java:202)
...
Any clues what am I doing wrong? Or any better ways to call this stored function?
Update: upon trying #axtavt's suggestion, I get the following error:
ORA-14551: cannot perform a DML operation inside a query
The function indeed does extensive inserts/updates, so I guess the only way to run it would be using the stored procedure syntax. I just have no clue how to map the return value:
<sql-query name="TransferLocationFix" callable="true">
<return-scalar column="???" type="string"/>
{ ? = call Transferlocation_Fix(:mnemonic) }
</sql-query>
What should be the column? I will try an empty value...
Update2: that failed as well, with an SQL Grammar Exception... So I tried the JDBC way as suggested by Pascal, and it seems to work! I added the code in an answer below.
For further reference, here is my final solution:
CallableStatement statement = session.connection().prepareCall(
"{ ? = call Transferlocation_Fix(?) }");
statement.registerOutParameter(1, Types.VARCHAR);
statement.setString(2, "FC3");
statement.execute();
String result = statement.getString(1);
I am not 100% sure and I didn't test it but according to Hibernate's documentation:
16.2.2. Using stored procedures for querying
Hibernate3 provides support for
queries via stored procedures and
functions. Most of the following
documentation is equivalent for both.
The stored procedure/function must return a resultset as the first
out-parameter to be able to work with
Hibernate. An example of such a
stored function in Oracle 9 and higher
is as follows:
CREATE OR REPLACE FUNCTION selectAllEmployments
RETURN SYS_REFCURSOR
AS
st_cursor SYS_REFCURSOR;
BEGIN
OPEN st_cursor FOR
SELECT EMPLOYEE, EMPLOYER,
STARTDATE, ENDDATE,
REGIONCODE, EID, VALUE, CURRENCY
FROM EMPLOYMENT;
RETURN st_cursor;
END;
To use this query in Hibernate you
need to map it via a named query.
<sql-query name="selectAllEmployees_SP" callable="true">
<return alias="emp" class="Employment">
<return-property name="employee" column="EMPLOYEE"/>
<return-property name="employer" column="EMPLOYER"/>
<return-property name="startDate" column="STARTDATE"/>
<return-property name="endDate" column="ENDDATE"/>
<return-property name="regionCode" column="REGIONCODE"/>
<return-property name="id" column="EID"/>
<return-property name="salary">
<return-column name="VALUE"/>
<return-column name="CURRENCY"/>
</return-property>
</return>
{ ? = call selectAllEmployments() }
</sql-query>
Stored procedures currently only
return scalars and entities.
<return-join> and
<load-collection> are not supported.
16.2.2.1. Rules/limitations for using stored procedures
You cannot use stored procedures with
Hibernate unless you follow some
procedure/function rules. If they do
not follow those rules they are not
usable with Hibernate. If you still
want to use these procedures you have
to execute them via
session.connection(). The rules are
different for each database, since
database vendors have different stored
procedure semantics/syntax.
Stored procedure queries cannot be
paged with
setFirstResult()/setMaxResults().
The recommended call form is standard
SQL92: { ? = call
functionName(<parameters>) } or { ?
= call procedureName(<parameters>}. Native call syntax is not supported.
For Oracle the following rules apply:
A function must return a result set. The first parameter of a
procedure must be an OUT that returns
a result set. This is done by using a
SYS_REFCURSOR type in Oracle 9 or
10. In Oracle you need to define a REF CURSOR type. See Oracle literature
for further information.
...
As I said, I'm not sure but my understanding is that you'll have to use session.getConnection() here.
callable = true is for calling stored procedures with {? = call ...()} syntax. Oracle's select ... from dual syntax is a normal query, so you don't need callable = true:
<sql-query name="TransferLocationFix">
<return-scalar column="retVal" type="string"/>
select Transferlocation_Fix(:mnemonic) as retVal from dual
</sql-query>
I've run into a similar question/problem and I've come to realize the changes should be done on the sql part as hibernate works only with cursor returns. I've described everything here: http://www.len.ro/2011/10/call-oracle-procedure-from-hibernate/

Categories