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.
Related
I'm migrating OracleDB11g to MSSQL2014.
Currently getting following error when trying to save new data:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ID', table 'testDB.FILE_SETTINGS';
column does not allow nulls. INSERT fails.
My interpretation is that this is caused as the "native" ID generator differs between Oracle & MSSQL (Sequence vs. Identity).
In Oracle we had small customization to HIBERNATE_SEQUENCE:
alter sequence hibernate_sequence increment by 5;
...but thats all.
hibernate-mapping is originally like this:
<id name="id" column="ID" type="java.lang.Long">
<generator class="native">
</generator>
</id>
In MSSQL I have tried it like this with no luck:
<id name="id" column="ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">HIBERNATE_SEQUENCE</param>
</generator>
</id>
And in MSSQL server I have sequence (migration tool created):
HIBERNATE_SEQUENCE in testDB->Views->sys.sequences
Also found in (migration tool created):
testDB->Views->INFORMATION_SCHEMA.SEQUENCES
How should this be done properly as I want to retain the same way to generate identity as was in Oracle? Something wrong in MSSQL or in hibernate settings?
Hibernate version is quite old: 2.1.8
Your interpretation of the error is wrong. This error tells you nothing about sequence. It tells you that your testDB.FILE_SETTINGS has id column defined as NOT NULL but you try to insert NULL value here.
I don't see your code but I think there is something like this:
create table dbo.MyTbl_wrong (id int NOT NULL, col1 varchar(100) );
insert into dbo.MyTbl_wrong(col1) values ('1 str'), ('2 str'), ('3 str');
Cannot insert the value NULL into column 'id', table
'db2.dbo.MyTbl_wrong'; column does not allow nulls. INSERT fails. The
statement has been terminated.
What you should do instead is to use sequence in the default for your id column like this:
create sequence dbo.MySeq
start with 1;
create table dbo.MyTbl (id int NOT NULL default(next value for dbo.MySeq), col1 varchar(100) );
insert into dbo.MyTbl(col1) values ('1 str'), ('2 str'), ('3 str');
--select *
--from dbo.MyTbl;
-------
--id col1
--1 1 str
--2 2 str
--3 3 str
Answering own question if some day someone has similar issues:
Apparently there was nothing wrong with the settings I mentioned in original question, only that hibernate 2.1.8 seemed not to support the SEQUENCE id genererator. Also old hibernate obviously did not support the needed SQLServer2012Dialect.
Ended up updating the hibernate version to 4.3.11 (with its dependencies). This version got selected as it required the least amount of refactoring.
I had some issues with the dependencies as this old project was not using Maven.
Also faced this error as any DB query was attempted:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I found out that new hibernate version was defaulted to use lazy loading which was not supported in the old version. So I ended up fixing it with setting "lazy=false" in hibernate setting files.
You may see "org.hibernate.LazyInitializationException: could not initialize proxy - no Session" while upgrading from hibernate 2.1 to hibernate 3.0. You will suddenly find yourself puzzling what happened, it was working before update. Reasons is, Hibernate 3 introduced lazy loading as the default i.e. lazy="true". If you want it to work the same as before you can mark everything as lazy="false". Alternatively you'll have to start eagerly initialising your entities and associations.
Read more: http://javarevisited.blogspot.com/2014/04/orghibernatelazyinitializationException-Could-not-initialize-proxy-no-session-hibernate-java.html#ixzz56ahBmiBl
I am new to esper. I want to store in mysql database event when esper identify event which satisfy the eql query.First i look up this example Esper: How to configure Esper to connect a Relational Database, through a JDBC, using Esper's configuration API and try to come up with solution.
<plugin-loader name="EsperIODBAdapter" class-name="com.espertech.esperio.db.EsperIODBAdapterPlugin">
<config-xml>
<esperio-db-configuration>
<jdbc-connection name="database">
<drivermanager-connection class-name="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/CEP_DEMO"
user="user" password="password"/>
<connection-settings auto-commit="true" catalog="TEST"/>
</jdbc-connection>
<dml connection="database" stream="event" >
<sql>INSERT INTO BasicEvent(userId,eventId,eventUsage,eventDateTime) values(?,?,?,?) </sql>
<bindings>
<bindings>
<parameter pos="1" property="userId"/>
<parameter pos="2" property="eventId"/>
<parameter pos="3" property="eventUsage"/>
<parameter pos="4" property="eventDateTime"/>
</bindings>
</bindings>
</dml>
</esperio-db-configuration>
</config-xml>
</plugin-loader>
Then when i run the application it didn't insert data to table.I want to know my method is correct or is there any other method to configuration.
Thanks
Maybe check that no exceptions are logged or thrown and the you are indeed inserting into a stream called "event" with "insert into event ..."
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.
I am writing a query but it always says "No matching index found". I don't know why. My code is as below:
Query query = pm.newQuery(Classified.class);
query.setFilter("emp_Id == emp");
query.setOrdering("upload_date desc");
query.declareParameters("String emp");
List<Classified> results = (List<Classified>)query.execute(session.getAttribute("emp_Id").toString());
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes autoGenerate="true">
<datastore-index kind="Classified" ancestor="false">
<property name="emp_Id" direction="asc" />
<property name="category" direction="asc" />
<property name="upload_date" direction="desc" />
</datastore-index>
</datastore-indexes>
I have added the above index, but it did not help.
I believe you need to configure a Datastore Index. There's probably one already generated for you in Eclipse at WEB-INF/appengine-generated/datastore-indexes-auto.xml that you just need to copy to WEB-INF/datastore-indexes.xml and deploy again.
Because this needs to be somewhere on the internet...
I kicked myself when I found this out
The error is you do not have a index matching what the query would like to perform. You can have multiple indexes for each entity.
In the Logcat, error, it will tell you exactly what index to set and what order the elements need to be.
ie, if the error says it wants (it wont be nicely formatted):
<datastore-index kind="Classified" ancestor="false">
<property name="category" direction="desc" />
<property name="upload_date" direction="desc" />
</datastore-index>
then Project -> war -> WEB-INF -> appengine-generated -> datastore-indexes-auto.xml and add exactly that. Then, redeploy the project.
Next go into your Google Cloud Console and look at Datastore -> indexes. It should say that the index is being prepared (This goes quicker if you can kill all apps connected and shut down the instance in the console).
Once this has moved into the list of other indexes, rerun the your application and it wont error out with regards to the index anymore.
Go get it Gentlemen/Ladies
The index you define must hold all possible results in the order they will be returned. Your query asks for a particular emp_Id, ordered by upload_date, but your index is ordered primarily by category.
Try removing the category line from your index definition, or swapping the order of category and upload_date, to make upload_date the primary sort order for the index. If another part of your code relies on the category line, you may have to make two separate indices (which incurs some computational cost).
Edit: see comment below by Nick Johnson re. extra parameters.
I am running into this issue at the moment when doing a single property query such as:
const query = datastore
.createQuery('Emailing_dev')
.filter('status', '=', 'Scheduled')
In my case, I should not be getting any errors, however I get Error 9: No matching index found.
If I defined the single property index twice in the yaml, it works:
indexes:
- kind: Emailing_dev
properties:
- name: status
- name: status
but this for sure must be a bug..!!
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/