I am trying to invoke the stored procedure below from my Java Code.
public void runProcedure(String accountId, String date, String receiverId, int seqNo) {
final SimpleJdbcCall transactionCall = new SimpleJdbcCall(this.jdbcTemplate)
.withSchemaName("CUSTOM")
.withProcedureName("PROC_REPORT_STATEMENT");
SqlParameterSource in = new MapSqlParameterSource()
.addValue("accountId", accountId)
.addValue("sdate", date)
.addValue("recvID", receiverId)
.addValue("seqNo", seqNo);
transactionCall.execute(in);
}
If executed on Toad with user USER1 it works as expected.
However, using the same user in my Java code returns the error below
Error in Executing Procedure CallableStatementCallback; bad SQL grammar [{call CUSTOM.PROC_REPORT_STATEMENT(?, ?, ?, ?)}]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 14:
CREATE OR REPLACE PROCEDURE CUSTOM.PROC_REPORT_STATEMENT(
accountId IN VARCHAR2,
sdate IN DATE,
recvID IN VARCHAR2,
seqNo IN NUMBER
) AS
....
I have carried out all that was requested here and still not able to find a solution.
I have no clue what to do next
Is your CUSTOM.PROC_REPORT_STATEMENT procedure valid?
In the Java code you wrote .addValue("accountId", accountId) but the parameter name in the stored procedure is accounted. Isn't it a problem?
I found out from the inner exception that it was failing because of the error below:
ORA-06502: PL/SQL: numeric or value error: number precision too large ORA-06512
The culprit: One of the variables
openbal NUMBER (10,2);
A query in the procedure was trying to fetch a value greater than the variable declared to hold the fetched result
I had to change it to something larger.
openbal NUMBER (25,2);
Related
Actually i am stuck with quite a time now regarding the below issue.
Does anyone has implemented Oracle Stored procedure calling through Java, i have implemented but getting the below error 'invalid column type 16 error'
"stack_trace":"org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call POST_CYCLE_TFO_STAT_PKG.INSERT_CYCLE_STATUS(?, ?, ?, ?)}]; SQL state [99999]; error code [17004]; Invalid column type: 16; nested exception is java.sql.SQLException: Invalid column type: 16\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89)\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1108)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1147)\r\n\tat org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:412)\r\n\tat org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:372)\r\n\tat org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:198)\r\n\tat com.mastercard.settlment.axon.payment.request.status.dao.AxonPaymentRequestCycleEventStatusDao.getCycleEventStatus(AxonPaymentRequestCycleEventStatusDao.java:46)\r\n\tat
my procedure syntax is:
PROCEDURE insert_cycle_status (SETTLEMENT_DATE_MANUAL IN DATE,
DEBUG_FLAG IN OUT BOOLEAN,
ERROR_INFO OUT VARCHAR2,
RESULT OUT BOOLEAN);
And my Java code is like below:
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate)
.withoutProcedureColumnMetaDataAccess()
.withProcedureName(CYCLE_EVENT_STATUS_PROCEDURE)
.declareParameters(new SqlParameter("SETTLEMENT_DATE_MANUAL", Types.DATE))
.declareParameters(new SqlParameter("DEBUG_FLAG", Types.BOOLEAN))
.declareParameters(new SqlOutParameter("ERROR_INFO", Types.VARCHAR))
.declareParameters(new SqlOutParameter("RESULT", Types.BOOLEAN));
SqlParameterSource in = new MapSqlParameterSource()
.addValue("SETTLEMENT_DATE_MANUAL", null)
.addValue("DEBUG_FLAG", 1);
Map<String, Object> result = call.execute(in);
Can anyone share any pointers on this, regarding the issue, it will be really helpful.
Thanks! In Advance
The main problem here is that Oracle JDBC Driver doesn't support passing booleans into Stored Procedures
You could use a neat trick to pass an IN boolean parameter as described in the other answer but this will not work for IN OUT parameters.
So as a workaround you'll have to wrap the stored procedure using the INT parameters instead of BOOLEAN
-- wrapper procedure
create or replace PROCEDURE insert_cycle_status2 (SETTLEMENT_DATE_MANUAL IN DATE,
DEBUG_FLAG IN OUT INT, /* Wrap BOOLEAN with INT */
ERROR_INFO OUT VARCHAR2,
RESULT OUT INT) as
v_DEBUG_FLAG BOOLEAN := (DEBUG_FLAG != 0);
v_RESULT BOOLEAN := (RESULT != 0);
begin
insert_cycle_status(SETTLEMENT_DATE_MANUAL,v_DEBUG_FLAG, ERROR_INFO, v_RESULT);
if v_RESULT THEN
RESULT := 1;
else
RESULT := 0;
end if;
if v_DEBUG_FLAG THEN
DEBUG_FLAG := 1;
else
DEBUG_FLAG := 0;
end if;
end;
/
Than your code will work simple by substituting both Types.BOOLEAN with Types.INTEGER
Update for Oracle 12.2
As demonstrated here the Oracle 12.2 support native binding of PLSQL_BOOLEAN.
Applied on the the original procedure insert_cycle_status the working solution would be as follows:
// works in Oracle Release 12.2+
stmt = con.prepareCall("{ call insert_cycle_status(?,?,?,?)}")
stmt.setDate(1, java.sql.Date.valueOf("2020-11-21"));
stmt.setObject(2,true,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN) /* BOOLEAN parameter */
stmt.registerOutParameter(2,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN)
stmt.registerOutParameter(3,Types.VARCHAR)
stmt.registerOutParameter(4,oracle.jdbc.OracleTypes.PLSQL_BOOLEAN)
stmt.execute()
I am trying to get total number of points back from my MySQL database using JDBC and prepared statements. I currently have
private static final String SELECT_TOTAL_POINTS_FROM_LEVEL_BY_CUSTOMER =
"select sum(points) from level_up where customer_id = ?";
#Override
public int getTotalLevelUpPointsByCustomerId(int customerId) {
int points = jdbcTemplate.queryForObject(SELECT_TOTAL_POINTS_FROM_LEVEL_BY_CUSTOMER,
Integer.class);
return points;
}
and my controller method is
#GetMapping("/points/{customerid}")
ResponseStatus(HttpStatus.OK)
public int getTotalPoints(#PathVariable("customerid") int customerId) {
return service.getTotalPoints(customerId);
}
How can i just get the points back from the database with just the customer id?
ERROR BELOW
"message": "StatementCallback; bad SQL grammar [select sum(points) from level_up where customer_id = ?]; nested exception is java.sql.SQLSyntaxErrorException: 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 '?' at line 1",
You were using a method that doesn’t allow for passing arguments. Use a method that allows for passing in arguments, like: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html#queryForObject-java.lang.String-java.lang.Object:A-int:A-java.lang.Class-
In my stored procedure, I have four parameters. One of the parameters has both IN and OUT. I am facing issues while accessing parameter with IN and Out.
In normal approach (using CallableStatement) I am able to fetch the results. I am facing this issue when using CallableStatementCreatorFactory (using this to avoid Sonarqube issue). I am looking for a solution using CallableStatementCreatorFactory. I cannot make any change in the stored procedure.
Procedure
PROCEDURE SOMENAME (
applicationname IN VARCHAR2,
username IN OUT VARCHAR2,
sessionid IN VARCHAR2 DEFAULT NULL,
usertype OUT VARCHAR2,
Spring boot Code
public static final String STORED_PROCEDURE_SOME_NAME = "{call TEST.PKG.SOMENAME(?,?,?,?)}";
CallableStatementCreatorFactory callableStatementCreatorFactory = new CallableStatementCreatorFactory(STORED_PROCEDURE_SOME_NAME);
callableStatementCreatorFactory.addParameter(new SqlParameter("APPLICATIONNAME", OracleTypes.VARCHAR));
callableStatementCreatorFactory.addParameter(new SqlParameter("USERNAME", OracleTypes.VARCHAR));
callableStatementCreatorFactory.addParameter(new SqlParameter("sessionid", OracleTypes.VARCHAR));
//callableStatementCreatorFactory.addParameter(new SqlOutParameter("USERNAME", OracleTypes.VARCHAR)); - throwing issue
callableStatementCreatorFactory.addParameter(new SqlOutParameter("usertype", OracleTypes.VARCHAR));
final Map<String, Object> param = new HashMap<>();
param.put("APPLICATIONNAME", applicationName);
param.put("USERNAME", userName);
param.put("sessionid", sessionGuid);
CallableStatementCallback<User> callableStatementCallback = new CallableStatementCallback<User>()
{
#Override
public User doInCallableStatement(CallableStatement callableStatement) throws SQLException
{
try
{
callableStatement.execute();
User userModel = new User();
//userModel.setUserName(callableStatement.getString(2)); - throwing issue
userModel.setUserType(callableStatement.getString(4));
return populateUser(callableStatement);
}
finally
{
try
{
callableStatement.close();
}
catch (SQLException e)
{
LOGGER.error(MESSAGE_ERROR_CALLABLESTATEMENT_CLOSE, e);
}
}
}
};
CallableStatementCreator callableStatementCreator = callableStatementCreatorFactory.newCallableStatementCreator(param);
userModel = jdbcTemplate.execute(callableStatementCreator, callableStatementCallback);
When I add an additional '? 'in the query, I get the following exception:
org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call TEST.PKG.SOMENAME(?,?,?,?,?)}]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'SOMENAME'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
When I uncomment the following line I get the following issue (removed additional question mark):
callableStatementCreatorFactory.addParameter(new SqlOutParameter("USERNAME", OracleTypes.VARCHAR));
Exception
org.springframework.jdbc.InvalidResultSetAccessException: CallableStatementCallback; invalid ResultSet access for SQL [{call TEST.PKG.SOMENAME(?,?,?,?)}]; nested exception is java.sql.SQLException: Invalid column index
When I uncomment the following line I get the following error:
userModel.setUserName(callableStatement.getString(TWO)); (after commenting previous line and removing one addtional ?)
Exception
org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call TEST.PKG.SOMENAME(?,?,?,?)}]; SQL state [99999]; error code [17021]; Missing defines; nested exception is java.sql.SQLException: Missing defines
Your parameter is an IN OUT parameter so you should use a SqlInOutParameter for it.
Replace the line
callableStatementCreatorFactory.addParameter(new SqlParameter("USERNAME", OracleTypes.VARCHAR));
with
callableStatementCreatorFactory.addParameter(new SqlInOutParameter("USERNAME", OracleTypes.VARCHAR));
Don't add the extra ?, there are four parameters to the stored procedure.
Delete the commented-out line that tries to create a SqlOutParameter for USERNAME. However, you should be able to uncomment the line
//userModel.setUserName(callableStatement.getString(2)); - throwing issue
and use this line to read the username that you get back from the database.
I made these modifications to your code and was able to use it to call a procedure with the same signature as yours and read data back from the procedure.
Incidentally, don't close the statement within the CallableStatementCallback: I found that this causes an exception because Spring will do other stuff with the statement after you've finished with it, but it can't do this if you've closed the statement. Spring will close the statement when it has finished with it. One of the benefits of using Spring to do JDBC is that it handles a lot of the tedious boilerplate stuff like this.
Here is my code..I got error
"UCanAccess error - net.ucanaccess.jdbc.UcanaccessSQLException: incompatible data type in operation: at following line..
PreparedStatement pStmt = conn.prepareStatement(sql)
public void showCeilingMaterials(Site_Details site_detail)
{
String sql="SELECT SiteName, SUM(PlanTileQuantity), SUM(PlanTilePrice), SUM(PellingQuantity),SUM(PellingPrice), SUM(PowderQuantity),SUM(PowderPrice),SUM(LpattiQuantity),SUM(LpattiPrice),LpattiSize,SUM(CeilingTotalPrice) FROM CeilingMaterials Where SiteName='?' AND Date<='?' AND Date>=?";
try (PreparedStatement pStmt = conn.prepareStatement(sql)) {
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
java.util.Date parsed = format.parse(site_detail.getStartDate());
java.sql.Date sql_date1 = new java.sql.Date(parsed.getTime());
format.format(sql_date1);
java.util.Date parsed1 = format.parse(site_detail.getEndDate());
java.sql.Date sql_date2 = new java.sql.Date(parsed1.getTime());
format.format(sql_date2);
pStmt.setString(1, site_detail.getSiteName());
pStmt.setDate(2, sql_date1);
pStmt.setDate(2,sql_date2);
ResultSet rs= pStmt.executeQuery();
while(rs.next()){
showCeil.setSiteName(rs.getString("SiteName"));
showCeil.setTileQuantity(rs.getString("PlanTileQuantity"));
showCeil.setTilePrice(rs.getString("PlanTilePrice"));
showCeil.setPellingQuantity(rs.getString("PellingQuantity"));
showCeil.setPellingPrice(rs.getString("PellingPrice"));
showCeil.setLpattiQuantity(rs.getString("LpattiQuantity"));
showCeil.setLpattiPrice(rs.getString("LpattiPrice"));
showCeil.setLpattiSize(rs.getString("LpattiSize"));
showCeil.setPowderQuantity(rs.getString("PowderQuantity"));
showCeil.setPowderPrice(rs.getString("PowderPrice"));
showCeil.setTotalCeilingPrice(rs.getString("CeilingTotalPrice"));
show_ceil_w=new Site_Details_Show_Interface();
show_ceil_w.showGui(showCeil);
}
}
}
The SQL command text for a parameterized query must never include quotes (or other delimiters) around parameter placeholders. You have the following, which is incorrect:
... Where SiteName='?' AND Date<='?' AND Date>=?
Specifically, it is Date<='?' that is causing the error cited in the question, although the error message is slightly different in newer versions of UCanAccess (in this case, v3.0.2):
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 incompatible data types in combination
Instead, you need to have
... Where SiteName=? AND [Date]<=? AND [Date]>=?
[Note that Date is a reserved word (built-in function name) in Access so you should use square brackets around it if you want to refer to a column named Date.]
Once that error is corrected then other errors in your SQL manifest themselves. The next one you will have to address is:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 expression not in aggregate or GROUP BY columns: PUBLIC.CEILINGMATERIALS.SITENAME
because you have included SiteName in your list of columns to be returned, but it is not part of an aggregate function (e.g., MIN(), MAX()) or a GROUP BY clause. You have that same problem with LpattiSize as well.
You also have
pStmt.setDate(2, sql_date1);
pStmt.setDate(2,sql_date2);
where you have assigned a value to parameter #2 twice (so parameter #3 has no value).
Finally, be aware that when you SUM() a column without providing an alias, as in
SELECT ... SUM(PlanTileQuantity), ...
the resulting column will not be named "PlanTileQuantity". UCanAccess will assign it an arbirtary column name like "C1", "C2", etc.. It is always best to explicitly assign an alias, e.g.,
SELECT ... SUM(PlanTileQuantity) AS SumOfPlanTileQuantity, ...
I have a SQL Server Stored Procedure that looks like this:
CREATE PROCEDURE [dbo].[my_stored_procedure]
(
#num INT,
#name VARCHAR(50),
#start_date DATETIME,
#end_date DATETIME
)
AS
BEGIN
...
END
And an Entity Object with a NamedNativeQuery that looks like this:
#Entity
#NamedNativeQuery(
name = "myObject.myStoredProcedure",
query = "call my_stored_procedure(:num, :name, :start_date, :end_date)",
callable = true,
readOnly=true,
resultSetMapping="implicit"
)
#SqlResultSetMapping(
name="implicit",
entities=#EntityResult(entityClass=org.mycompany.object.MyObject.class)
)
public class MyObject implements Serializable {
...
But when I try to call it in my DAO like so:
List<MyObject> objects = (List<MyObject>) getHibernateTemplate().execute(new HibernateCallback() {
#Override
public Object doInHibernate(Session session) throws HibernateException {
return session.getNamedQuery("myObject.myStoredProcedure")
.setInteger("num", num)
.setString("name", name)
.setDate("start_date", startDate)
.setDate("end_date", endDate)
.list();
}
});
But I get this error:
12 May 2010 10:55:43,040 100833 [http-8080-Processor23] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid parameter index 4.
12 May 2010 10:55:43,042 100835 [http-8080-Processor23] FATAL org.mycompany.web.controller.BasePagingController - org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
It seems like it's expecting another parameter, like a return parameter, but I tried adding a '?' to the call and all the Hibernate documentation suggests against this.
Any help would be appreciated. Thanks
The Hibernate Documentation on calling stored procedures states:
The recommended call form is standard SQL92: { ? = call functionName(<parameters>) } or { ? = call procedureName(<parameters>) }. Native call syntax is not supported.
So the 4th line in your second snippet should probably be
query = "{ ? = call my_stored_procedure(:num, :name, :start_date, :end_date) }",
I don't know, what your procedure returns, but you might want to check the following as well.Even more Hibernate Documentation:
For Sybase or MS SQL server the
following rules apply:
The procedure must return a result
set. Note that since these servers can
return multiple result sets and update
counts, Hibernate will iterate the
results and take the first result that
is a result set as its return value.
Everything else will be discarded.
If you can enable SET NOCOUNT ON in your
procedure it will probably be more
efficient, but this is not a
requirement.