Getting oracle Stored procedure resultset in java spring mvc - java

I have the following stored procedure which takes three parameters and returns three ref cursors.
variable id refcursor
variable item refcursor
variable amount refcursor
exec getdata(123,date1,date2, :id, :item, :amount) ;
print id;
print item;
print amount;
i have three resultsets for this stored procedure output. How can i call this in spring mvc and display these three resultsets. I was using the following code to fetch the data through sql query. But now i have developed a stored procedure. so how can i call this SP output insted of my query output.
public Optional<List<student>> getStudentDetails(String id) {
NamedParameterJdbcTemplate parameterJdbcTemplate = new
NamedParameterJdbcTemplate(dataSource);
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("Id", id);
List<student> studentList =
parameterJdbcTemplate.query(StudentQueryRepository.STUDENT_DETAIL_QUERY,
namedParameters, new studentDecodeRowMapper());
if (studentList.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(studentList);
}
}

Try this:
List<CommunicationContact> campaigns = jdbcTemplate.execute(
new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con) throws SQLException {
CallableStatement cs = con.prepareCall("{? = call MY_SERVICES.GET_CAMPAIGNS(?,?)}");
cs.registerOutParameter(1, OracleTypes.CURSOR);
cs.setString(2, customer);
cs.setString(3, channel);
return cs;
}
},
new CallableStatementCallback<List<CommunicationContact>>() {
#Override
public List<CommunicationContact> doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
cs.execute();
ResultSet rs = (ResultSet) cs.getObject(1);
List<CommunicationContact> communications = commContactRsExtractor.extractData(rs);
return communications;
}
}
);
And the I have a function on the database:
FUNCTION GET_CAMPAIGNS(p_cust IN VARCHAR2,
p_channel IN VARCHAR2)
RETURN SYS_REFCURSOR
IS
l_campaigns_cursor SYS_REFCURSOR;
BEGIN
BEGIN
OPEN l_campaigns_cursor FOR
SELECT...
EXCEPTION
WHEN OTHERS THEN
...
END;
RETURN l_campaigns_cursor;
END GET_CAMPAIGNS;
I believe that a stored procedure with out parameter will also work.

Related

Resolving Database Stored XSS issues from Checkmarx

Here I am getting Error at the List<Data> dataList = jdbcTemplate.query location.
Checkmarx says:
AppServices/src/main/java/com/mbusa/app/dao/impl/AppRequestDAOImpl.java
gets data from the database, for the query element. This element’s
value then flows through the code without being properly filtered or
encoded and is eventually displayed to the user in method
getRequestDetail at line 117 of
AppWeb/src/main/java/com/mbusa/app/controllers/AppRequestController.java.
This may enable a Stored Cross-Site-Scripting attack.
List<Data> dataList = jdbcTemplate.query(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(fSQL);
int index = 1;
for(Object param: effParams) {
pstmt.setString(index, (String) param);
index++;
}
return pstmt;
}
}, new RequestMapper());
public class RequestMapper implements RowMapper<Data> {
#Override
public Data mapRow(ResultSet rs, int rowNum) throws SQLException {
Data data = new Data();
data.setName(rs.getString("name"));
return data ;
}
}
I have added PreparedStatement here to resolve this issue and also tried adding HtmlUtil.htmlEscape upon output data, but still could not resolve this issue.
Can anyone help with this issue?

SimpleJDBC call for stored procedure in ORACLE database

I am trying to implement code which will have resultset using simpljdbccall or jdbccall or namedtemplatejdbc
Code will use my stored procedure which is database proc having input parameter and an REF cursor.
I did not found any code which will help me to extract cursor as output to have all multiple rows details in in my resultset using JDBC
DATABASE PROCEDURE
BOOKING_PG.get_infant_info_pr(
c_booking_id IN T_BOOKED_INFANT_INFO.BOOKING_ID%TYPE,
c_booked_infant_details OUT booked_infant_details
)
OPEN c_booked_infant_details FOR
SELECT
BOOKING_ID c_booking_id,
BOOKED_INFANT_INFO_ID c_booked_infant_info_id,
BOOKED_ADULT_PAX_INFO_ID c_booked_adult_pax_info_id,
FROM T_BOOKED_INFANT_INFO T
WHERE T.BOOKING_ID = c_booking_id
and T.STATUS_ID = 1;
JAVA Code
SimpleJdbcCall call = new SimpleJdbcCall(dataSource2)
.withCatalogName("BOOKING_PG")
.withProcedureName("get_infant_info_pr")
.withoutProcedureColumnMetaDataAccess()
.returningResultSet("rs1", new ParameterizedRowMapper() {
#Override
public Object[] mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Object[]{rowNum, rs.getLong("c_booking_id"), rs.getLong(c_booked_infant_info_id) , rs.getLong(c_booked_adult_pax_info_id)};
}
});
SqlParameterSource in = new MapSqlParameterSource()
.addValue(C_BOOKING_ID, bookingId);
Map<String, Object> res = call.execute(in);
List<Object[]> l1 = (List<Object[]>)res.get("rs1");
It is throwing SQL error
org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call EURONOVA.BOOKING_PG.GET_INFANT_INFO_PR(?)}]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'GET_INFANT_INFO_PR'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
I am not sure if there is something wrong in the code or we have to follow some different way to get resultset in simplejdbc call
Can someone please help me in this topic?
First create a class having similar data type and names which your cursor returns.
In your case create a class named BookedInfantDetails.java
public class BookedInfantDetails{
private int bookingId;
private int bookedInfantinfoId;
private int bookedadultpaxinfoid;
public int getBookingId() {
return bookingId;
}
public void setBookingId(int bookingId) {
this.bookingId = bookingId;
}
public int getBookedInfantinfoId() {
return bookedInfantinfoId;
}
public void setBookedInfantinfoId(int bookedInfantinfoId) {
this.bookedInfantinfoId = bookedInfantinfoId;
}
public int getBookedadultpaxinfoid() {
return bookedadultpaxinfoid;
}
public void setBookedadultpaxinfoid(int bookedadultpaxinfoid) {
this.bookedadultpaxinfoid = bookedadultpaxinfoid;
}
}
Now declare in and out parameters in the jdbccall and map the ref cursor to the class using beanproperty rowmapper.
SimpleJdbcCall call = new SimpleJdbcCall(dataSource2)
.withCatalogName("BOOKING_PG")
.withProcedureName("get_infant_info_pr")
.withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("c_booking_id", OracleTypes.Integer),
new SqlParameter("c_booked_infant_details", OracleTypes.CURSOR),
.returningResultSet("c_booked_infant_details",
BeanPropertyRowMapper.newInstance(BookedInfantDetails.class));
SqlParameterSource in = new MapSqlParameterSource()
.addValue(C_BOOKING_ID, bookingId);
Map<String, Object> res = call.execute(in);
List<BookedInfantDetails> l1=
(List<BookedInfantDetails>)res.get("c_booked_infant_details");
Find Our more details on spring docs....
https://docs.spring.io/spring-data/jdbc/old-docs/1.2.1.RELEASE/reference/html/orcl.datatypes.html#orcl.datatypes.ref_cur

Spring Transactional not using same JDBC connection

Can someone please tell me why do i sql get exception that "Invalid object #EMP_TEMP" even if i am running both queries under same transaction?
#Transactional
public Map<String, EventType> findEventsByDateRange(final Date startTimestamp, final Date endTimestamp) throws Exception {
log.debug("Fetching Events Data");
String EVENT_QUERY = "Select ID, Name, Status, JoinDate into #EMP_TEMP from EMPLOYEE where JoinDate >= ? and JoinDate < ?";
this.jt.execute(EVENT_QUERY, new PreparedStatementCallback<Boolean>() {
#Override
public Boolean doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {
preparedStatement.setTimestamp(1, new java.sql.Timestamp(startTimestamp.getTime()));
preparedStatement.setTimestamp(2, new java.sql.Timestamp(endTimestamp.getTime()));
return preparedStatement.execute();
}
});
//this.jt.execute(EVENT_QUERY);
return this.jt.query("SELECT * from #EMP_TEMP "
, DataExtractor.eventDataExtractor);
}
However if i change code as below then it doesn't complaint. but problem in this approach is that i cannot pass any parameters into first query:
#Transactional
public Map<String, EventType> findEventsByDateRange(final Date startTimestamp, final Date endTimestamp) throws Exception {
log.debug("Fetching Events Data");
String EVENT_QUERY = "Select ID, Name, Status, JoinDate into #EMP_TEMP from EMPLOYEE where JoinDate >= '2015-07-13 00:00:00.000' and JoinDate < '2015-07-14 00:00:00.000'";
/*this.jt.execute(EVENT_QUERY, new PreparedStatementCallback<Boolean>() {
#Override
public Boolean doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {
preparedStatement.setTimestamp(1, new java.sql.Timestamp(startTimestamp.getTime()));
preparedStatement.setTimestamp(2, new java.sql.Timestamp(endTimestamp.getTime()));
return preparedStatement.execute();
}
});*/
this.jt.execute(EVENT_QUERY);
return this.jt.query("SELECT * from #EMP_TEMP "
, DataExtractor.eventDataExtractor);
}
Finally i found out that root cause of the problem is not spring but sql server.
In SQL Server 2005, SQL Server 2000, and SQL Server 7.0, the prepared statements cannot be used to create temporary objects and cannot reference system stored procedures that create temporary objects, such as temporary tables. These procedures must be executed directly.
Since i was trying to create the temp table by jdbcTemplate method execute(String sql, PreparedStatementCallback action) which uses prepared statement therefore it was not working.
Instead of that when i created temp table using execute(String sql) it is working.

JDBC Template querying

I am trying to execute this method using jdbc template:
public String getClientName(String uuid) {
System.out.println("UUID here in the dao layer is: " + uuid);
String sql = "Select email from client where uuid=?";
return jdbcTemplate.query(sql, new ResultSetExtractor<String>() {
#Override
public String extractData(ResultSet rs) throws SQLException, DataAccessException {
return rs.getString("email");
}
});
}
However I am getting this error:
SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [Select email from client where uuid=?]; nested exception is org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying =?
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Where am I going wrong?
You are not passing the uuid which you got as a parameter to your method. You could do use the api like:
Object sqlParameters[] = {uuid};
return jdbcTemplate.query(sql, sqlParameters,
new ResultSetExtractor<List<String>>() {
#Override
public List<String> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<String> emailList=new ArrayList<String>();
while (rs.next()) {
emailList.add(rs.getString("email"));
}
return emailList;
}});
You're not using your uuid parameter anywhere... I suspect you actually want:
return jdbcTemplate.query(sql, new Object[] { uuid },
new ResultSetExtractor<String>() { ... });
That way uuid will be used as the value for the parameter in your SQL.

java.sql.SQLException: Invalid value for getInt() - 'Glomindz Support'

I am not able to retrieve column values from my database table with the following coding a message has been displayed in the console:
java.sql.SQLException: Invalid value for getInt() - 'Glomindz Support'
My code is:
package com.glomindz.mercuri.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import com.glomindz.mercuri.util.MySingleTon;
public class UserServicesDAO {
private Connection connection;
public UserServicesDAO() {
// connection = new MySingleTon().getConnection();
connection = MySingleTon.getInstance().getConnection();
}
public void get_all_data() {
}
public Map<Integer, String> get_all_data1() {
HashMap<Integer, String> result = new HashMap<Integer, String>();
String query = "SELECT * FROM spl_user_master";
try {
PreparedStatement stmt = connection.prepareStatement(query);
boolean execute = stmt.execute();
System.out.println(execute);
ResultSet resultSet = stmt.getResultSet();
System.out.println(resultSet.getMetaData());
while (resultSet.next()) {
result.put(resultSet.getInt(1), resultSet.getString("id"));
result.put(resultSet.getInt(2), resultSet.getString("name"));
result.put(resultSet.getInt(3), resultSet.getString("email"));
result.put(resultSet.getInt(4), resultSet.getString("mobile"));
result.put(resultSet.getInt(5), resultSet.getString("password"));
result.put(resultSet.getInt(6), resultSet.getString("role"));
result.put(resultSet.getInt(7), resultSet.getString("status"));
result.put(resultSet.getInt(8),
resultSet.getString("last_update"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
new UserServicesDAO().get_all_data1();
}
}
My db table schema is:
id name email mobile password role status last_update
1 Glomindz Support support#glomindz.com 9854087006 cbf91a71c11d5ec348b0c7e9b2f0055e admin 1 2013-05-02 22:05:14
2 Amarjyoti Das amarjyotidas#splcare.com 9864092598 88f2dccb02b2a20615211e5492f85204 admin 1 2013-04-26 05:44:41
You retrieve every column as an int for the key. I assume that some of these columns represent Strings or Dates.
while(resultSet.next()){
result.put(resultSet.getInt(1),resultSet.getString("id"));
result.put(resultSet.getInt(2),resultSet.getString("name")); //Most likely a String
result.put(resultSet.getInt(3),resultSet.getString("email"));
result.put(resultSet.getInt(4),resultSet.getString("mobile"));
result.put(resultSet.getInt(5),resultSet.getString("password"));
result.put(resultSet.getInt(6),resultSet.getString("role"));
result.put(resultSet.getInt(7),resultSet.getString("status"));
result.put(resultSet.getInt(8),resultSet.getString("last_update")); //Most likely a date
}
The inconsistencies between the data types and the object/value returned by the getInt() method causes the error. I would suggest building/modeling an object in your domain that stores rows from the table. Something like:
public class User{
private Integer id;
private String name;
private String email;
private String mobile;
private String password;
private String role;
private String status;
private Date lastUpdate;
/* Get and set methods for each field */
}
Then build a Map containing the object as the value and the id as the key:
//Use Map interface here, also notice generic arguments <Integer,User>
Map<Integer, User> result = new HashMap<Integer, User>();
try {
PreparedStatement stmt = connection.prepareStatement(query);
boolean execute = stmt.execute();
System.out.println(execute);
ResultSet resultSet = stmt.getResultSet();
System.out.println(resultSet.getMetaData());
while(resultSet.next()){
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name");
user.setEmail(resultSet.getString("email");
//do this for each field, using appropriate method for type...
//then add to map
result.put(user.getId(), user);
}
I think you need all your data from the table as a Map. But you may have multiple rows in your DB, therefore you basically want a list of maps! Modify your method to something like this:-
public List<Map<Integer, String>> get_all_data1() {
List<Map<Integer, String>> allRows = new ArrayList<Map<Integer, String>>();
String query = "SELECT * FROM spl_user_master";
try {
PreparedStatement stmt = connection.prepareStatement(query);
boolean execute = stmt.execute();
System.out.println(execute);
ResultSet resultSet = stmt.getResultSet();
System.out.println(resultSet.getMetaData());
while (resultSet.next()) {
Map<Integer, String> result = new HashMap<Integer, String>();
result.put(1, resultSet.getString("id"));
result.put(2, resultSet.getString("name"));
result.put(3, resultSet.getString("email"));
result.put(4, resultSet.getString("mobile"));
result.put(5, resultSet.getString("password"));
result.put(6, resultSet.getString("role"));
result.put(7, resultSet.getString("status"));
result.put(8, resultSet.getString("last_update"));
allRows.add(result);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return allRows;
}
Here, for every fetched record from the DB, the columns are put into the Map, and each map, represents a row, which is added to a List!
If you are using JPA annotations to map entity fields with db table, you need to use #Enumerated(EnumType.STRING) annotation on ENUM type entity fields.
This error is due to, while creating the table you may mentioned name column as INTEGER. So while retrieving it will get that column using getInt() method. But actually the column is of type STRING.
U should change the datatype of name column to STRING and this issue will be fixed automatically.
According to documentation, getInt() or getString() requires columnIndex or columnLabel to get value for that column in particular entry. To find the column index you need to use findColumn(name) method to get its columnIndex. So your code should be as follows:
while (resultSet.next()) {
result.put(resultSet.findColumn("id"), resultSet.getInt("id"));
result.put(resultSet.findColumn("name"), resultSet.getString("name"));
result.put(resultSet.findColumn("email"), resultSet.getString("email"));
result.put(resultSet.findColumn("mobile"), resultSet.getInt("mobile"));
result.put(resultSet.findColumn("password"), resultSet.getString("password"));
result.put(resultSet.findColumn("role"), resultSet.getString("role"));
result.put(resultSet.findColumn("status"), resultSet.getInt("status"));
result.put(resultSet.findColumn("last_update"),
resultSet.getString("last_update"));
}
Basically you need to get your values according to the datatype with which it had been saved in DB. Check available methods to retrieve values by Ctrl+Click on ResultSet class
Please check the syntax error for a small mistake for comma(,) you are added before the select statement
Example:
select id, name, mobile, address from table_name;
but you are using like
select id, name, mobile, address, from table_name;
please check and correct it

Categories

Resources