How to catch the SqlExceptionHelper in spring boot? - spring-boot

I could not capture that error that comes from the stored procedure that I created.
create procedure sp_users
#option int = 0,
#nom_user varchar(50) = null,
#ema_user varchar(50) = null
as
begin
set nocount on
begin try
if #option = 2
begin
if not exists (select * from tb_users where ema_user = #ema_user)
begin
insert into tb_users values (#nom_user,#ema_user)
end
else
begin
raiserror('The email already exists',16,1)
end
end
end try
begin catch
declare #errorMessage varchar(100), #errorSeverity int, #errorState int
set #errorMessage = error_message()
set #errorSeverity = error_severity()
set #errorState = error_state()
raiserror(#errorMessage,#errorSeverity,#errorState)
end catch
end
when I enter an email that already exists, it shows me the message.
Msg 50000, Level 16, State 1, Procedure sp_users, Line 71 [Batch Start Line 81]
The email already exists
this is the code that I made in spring boot
#Service
public class CrudUserService implements CrudUserDAO{
#PersistenceContext
private EntityManager em;
#SuppressWarnings({ "unchecked" })
#Override
public ValidateApiResponse MntUser(Integer op, String nom, String ema) {
ValidateApiResponse vapi = new ValidateApiResponse();
Session session = em.unwrap(Session.class);
try {
ProcedureCall call = session.createStoredProcedureCall("sp_users");
call.registerParameter(1, Integer.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(3, String.class, ParameterMode.IN).enablePassingNulls(true);
call.setParameter(1, op);
call.setParameter(2, nom);
call.setParameter(3, ema);
call.execute();
vapi.dTable = call.getResultList();
vapi.Attr = "OK";
} catch (Exception e) {
//vapi.Attr = "";
//vapi.Error = e.getMessage();
System.out.println(e.getMessage());
} finally {
session.close();
}
return vapi;
}
}
when I try to capture the error in spring boot I get this in the console. it shows me the message, but I can't capture that message from SqlExceptionHelper.
2019-12-30 19:19:22.892 WARN 10504 --- [nio-8090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 50000, SQLState: S0001
2019-12-30 19:19:22.893 ERROR 10504 --- [nio-8090-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : The email already exists
org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults

I have already solved it, but creating an output parameter.
procedure
create proc sp_users
#option int = 0,
#nom_user varchar(50) = null,
#ema_user varchar(50) = null,
#message_error varchar(50) = null output
as
begin
set nocount on
begin try
if #option = 2
begin
if not exists(select * from tb_users where ema_user = #ema_user)
begin
insert into tb_users values(#nom_user,#ema_user)
end
else
begin
set #message_error = 'The email already exists'
raiserror(#message,16,1)
end
end
end try
begin catch
print error_message()
end catch
end
spring boot
#Service
public class CrudUserService implements CrudUserDAO {
#PersistenceContext
private EntityManager em;
#SuppressWarnings({ "unchecked" })
#Override
public ValidateApiResponse MntUser(Integer op, String nom, String ema) {
ValidateApiResponse vapi = new ValidateApiResponse();
Session session = em.unwrap(Session.class);
ProcedureCall call = session.createStoredProcedureCall("sp_users");
call.registerParameter(1, Integer.class, ParameterMode.IN);
call.registerParameter(2, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(3, String.class, ParameterMode.IN).enablePassingNulls(true);
call.registerParameter(4, String.class, ParameterMode.OUT).enablePassingNulls(true);
call.setParameter(1, op);
call.setParameter(2, nom);
call.setParameter(3, ema);
call.execute();
String message = (String) call.getOutputParameterValue(4);
if (message == "" || message == null) {
vapi.dTable = call.getResultList();
vapi.Attr = "OK";
} else {
vapi.Attr = "";
vapi.Error = message;
}
return vapi;
}
}
This is the message I get when I enter an email that already exists.
"Msj": "Internal Server Error",
"MsjDetail": "The email already exists",
"dtCollection": [],
"MsjCode": 500

Related

Query for below issue

I want to insert one row for each unique b_id if the b_id doest have any row with data = x. The value for the new row will be same for
b_id, b_name but the value for data will be x and sequence will be 1 and existing sequence for that b_id should be updated by 1
DECLARE
CURSOR b_id_cursor IS
SELECT DISTINCT b_id
FROM md_details;
BEGIN
FOR b_id_rec IN b_id_cursor LOOP
IF NOT EXISTS (SELECT 1 FROM md_details WHERE b_id = b_id_rec.b_id AND data = 'INIT') THEN
INSERT INTO md_details (b_id, b_name, data, sequence)
SELECT b_id, b_name, 'INIT', 1
FROM md_details
WHERE b_id = b_id_rec.b_id
AND ROWNUM = 1;
UPDATE md_details
SET sequence = sequence + 1
WHERE b_id = b_id_rec.b_id;
END IF;
END LOOP;
END;
import java.util.ArrayList;
import java.util.List;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
public class AdGroupFinder {
private DirContext dirContext;
public AdGroupFinder(DirContext dirContext) {
this.dirContext = dirContext;
}
public List<String> getAdGroupsForUser(String userName) {
List<String> adGroups = new ArrayList<>();
try {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(objectClass=user)(sAMAccountName=" + userName + "))";
javax.naming.NamingEnumeration<javax.naming.directory.SearchResult> results =
dirContext.search("", searchFilter, searchControls);
while (results.hasMoreElements()) {
javax.naming.directory.SearchResult searchResult = results.nextElement();
javax.naming.directory.Attribute memberOfAttribute = searchResult.getAttributes().get("memberOf");
for (int i = 0; i < memberOfAttribute.size(); i++) {
String groupDN = (String) memberOfAttribute.get(i);
adGroups.add(groupDN.substring(0, groupDN.indexOf(",")));
}
}
} catch (javax.naming.NamingException e) {
e.printStackTrace();
}
return adGroups;
}
public List<String> getUsersForAdGroup(String adGroupName) {
List<String> users = new ArrayList<>();
try {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(objectClass=user)(memberOf=CN=" + adGroupName + ",OU=Groups,DC=example,DC=com))";
javax.naming.NamingEnumeration<javax.naming.directory.SearchResult> results =
dirContext.search("", searchFilter, searchControls);
while (results.hasMoreElements()) {
javax.naming.directory.SearchResult searchResult = results.nextElement();
javax.naming.directory.Attribute sAMAccountNameAttribute = searchResult.getAttributes().get("sAMAccountName");
users.add((String) sAMAccountNameAttribute.get());
}
} catch (javax.naming.NamingException e) {
e.printStackTrace();
}
return users;
}
}

oracle jdbc driver reports no primary key columns on a table that has a primary key

This was reported by HibernateTools Reverse Engineering, but it seems to be true.
oracle jdbc driver reports no primary key columns on a table that has a primary key.
#Test
public void checkTable() throws SQLException, IOException {
System.out.println("in check table");
assertNotNull(conn);
Statement s = conn.createStatement();
ResultSet rset = s.executeQuery("select user from dual");
rset.next();
String username = rset.getString(1);
rset.close();
try {
s.execute("drop table " + username + ".x");
} catch (Exception e) {
// nothing it might not exist
}
s.execute("create table " + username + ".x (y number)");
s.execute("alter table x add constraint x_pk primary key (y)");
DatabaseMetaData meta = conn.getMetaData();
final String[] tableTypes = new String[] { "TABLE", "VIEW" };
ResultSet rs = meta.getTables(null, username, "X",tableTypes);
rs.next();
String table = rs.getString("table_name");
System.out.println("table is " + table);
rs.close();
rs = s.executeQuery("select * from user_constraints where table_name = 'X'");
rs.next();
String type = rs.getString("constraint_type");
assertEquals("P",type); // primary key
rs.close();
rs = meta.getPrimaryKeys(null, username, "X");
rs.next();
logger.info("getting pk");
System.out.print("wtf");
int colCount = 0;
while (rs.next()) {
final String pkName = rs.getString("pk_name");
logger.info("pkName: {}", pkName);
int keySeq = rs.getShort("key_seq"); // TODO should probably be column seq
String columnName = rs.getString("column_name");
logger.warn("seq: {}, columnName: {}, keySeq, columnName");
colCount++;
}
System.out.println("colCount: " + colCount);
assertEquals(1,colCount);
}

Spring JdbcTemplate query parameters type error: Invalid column type

I use Spring Jdbc Template that way:
public List<User> getUsersForGrid(int rows, int page, String sidx,
String sord) {
int fromRecord = 0;
int toRecord = 0;
toRecord = page * rows;
fromRecord = (page - 1) * rows;
StringBuilder sqlB = new StringBuilder();
sqlB.append("SELECT user_id, username ");
sqlB.append("FROM users ");
sqlB.append("WHERE :fromRecord <= rownum AND rownum <= :toRecord ");
sqlB.append("ORDER BY %s %s ");
String sql = String.format(sqlB.toString(), sidx, sord);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("fromRecord", fromRecord);
params.addValue("toRecord", toRecord);
List<Map<String, Object>> rsRows = this.jdbcTemplate.queryForList(sql
.toString(),params);
List<User> users = new ArrayList<User>();
for (Map<String, Object> row : rsRows) {
BigDecimal id = (BigDecimal) row.get("user_id");
String username = (String) row.get("username");
User user = new User(id.intValue(), username);
users.add(user);
}
return users;
}
and get java.sql.SQLException: Invalid column type
sidx is column nate("user_id" for example) sord is asc/desc
When pass no params(execute only
sql.append("SELECT user_id, username ");
sql.append("FROM users ");
) everything is OK.
Update: Works with:
sqlB.append("WHERE ? <= rownum AND rownum <= ? ");
and
this.jdbcTemplate.queryForList(sql.toString(),new Object[]{fromRecord, toRecord});
Seems like problem with Spring MapSqlParameterSource and named parameters. I use Spring 3.1.3
DB is Oracle 11.2
describe users;
Name Null Type
------------------------------ -------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
USER_ID NOT NULL NUMBER
USERNAME NOT NULL VARCHAR2(40)
PASSWORD NOT NULL VARCHAR2(20)
ENABLED NOT NULL NUMBER
I think the problem is with your order by clause,
you are trying to dynamically change your order by clause.
Just try
StringBuilder sql = new StringBuilder();
sql.append("SELECT user_id, username ");
sql.append("FROM users ");
sql.append("WHERE :fromRecord <= rownum AND rownum <= :toRecord ");
sql.append("ORDER BY user_id asc ");
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("fromRecord", fromRecord);
params.addValue("toRecord", toRecord);
If the above works, then instead of using the MapSqlParameterSource for changing the order by clause use something like
StringBuilder sql = new StringBuilder();
sql.append("SELECT user_id, username ");
sql.append("FROM users ");
sql.append("WHERE :fromRecord <= rownum AND rownum <= :toRecord ");
sql.append("ORDER BY %s %s ");
//Format the sql string accordingly
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("fromRecord", fromRecord, Types.INTEGER);
params.addValue("toRecord", toRecord, Types.INTEGER);
Hope it helps.
try this
List<Map> rows = getJdbcTemplate().queryForList(sql);
for (Map row : rows) {
BigDecimal id = (BigDecimal) row.get("user_id");
String username = (String) row.get("username");
User user = new User(id.intValue(), username);
users.add(user);
}
ok try
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("fromRecord", fromRecord);
namedParameters.addValue("toRecord", toRecord);
namedParameters.addValue("sidx", sidx);
namedParameters.addValue("sord", sord);
return this.getNamedParameterJdbcTemplate().query(query,
namedParameters, new UserElementMapper());
public class UserMapper implements RowMapper<User> {
public EmailElement mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
emailElement.setID(rs.getInt("user_id"));
emailElement.setUsernameo(rs.getString("username"));
return user;
}
}

How to use jmeter to test an Oracle Stored Procedure with sys_refcursor return type?

I want to test an Oracle Stored Procedure by using jmeter.I have done everything but parameters.
And here is my SQL Query:
declare
outinfo varchar2(20);
outtable sys_refcursor;
begin
{call RK_JSCX(?,?)};
end;
The outtable in Oracle is a cursor.And i used resultSet to contain it in java.However,whatever i set in parameter types ,it said invalid type.
Sample Start: 2012-10-25 16:06:41 CST
Load time: 0
Latency: 0
Size in bytes: 25
Headers size in bytes: 0
Body size in bytes: 25
Sample Count: 1
Error Count: 1
Response code: null 0
Response message: java.sql.SQLException: Invalid data type: cursor
Response headers:
oracle.jdbc.driver.T4CConnection#58ba09
SampleResult fields:
ContentType: text/plain
DataEncoding: UTF-8
How can fix it?
Thanks!
Here is my code in java:
public String RK_JSCX() throws Exception {
RK_JSCX_Response response = null;
List<RK_JSCX_Outtable> list = null;
Connection con = null;
CallableStatement cs = null;
ResultSet rs = null;
String sql = null;
try {
sql = "{call RK_JSCX(?,?)}";
con = ConnectionUtils.getInstance().getConnect();
if (con.isClosed()) {
throw new IllegalStateException("ERROR.THE CONNECTION ISCLOSED");
}
cs = con.prepareCall(sql);
cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cs.registerOutParameter(2, Types.VARCHAR);
cs.execute();
rs = (ResultSet) cs.getObject(1);
list = new ArrayList<RK_JSCX_Outtable>();
while (rs.next()) {
RK_JSCX_Outtable out = new RK_JSCX_Outtable(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getInt(5), rs.getString(6));
list.add(out);
}
String outInfo = cs.getString(2);
response = new RK_JSCX_Response(list, outInfo);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (rs != null) {
rs.close();
if (cs != null) {
cs.close();
}
if (con != null) {
con.close();
}
}
} catch (SQLException e) {
System.out.println("Exception2");
e.printStackTrace();
}
}
return JSON.toJSONString(response);
}
This is how to do it:
SQL Query : call RK_JSCX(?,?)
Parameter values : OUT, OUT
Parameter types : OUT -10,OUT VARCHAR
-10 being the int value of OracleTypes.CURSOR
Variable names: cursor, outInfo
Names are what you want
JMeter allows using more types than java.sql.Types constants, in this case instead of using Constant names, you use integer values of constants.
Documentation has been clarified (in next JMeter version) , see:
https://issues.apache.org/bugzilla/show_bug.cgi?id=54048
Try with the following changes
change the syntax in calling the procedure to
cs = con.prepareCall("BEGIN RK_JSCX(?, ?); END;");
And I believe your first OUT parameter is VARCHAR2 right? so
cs.registerOutParameter(1, Types.VARCHAR);
then
use the following to cast CallableStatement
rs = ((OracleCallableStatement)cs).getCursor(2);
Update 1
I have changed your procedure to demonstrate working version
Procedure
CREATE OR REPLACE PROCEDURE rk_jscx (outtable OUT sys_refcursor,
outinfo OUT VARCHAR2
)
AS
BEGIN
OPEN outtable FOR
SELECT SYSDATE
FROM DUAL;
outinfo := 1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
outinfo := 2;
ROLLBACK;
END rk_jscx;
Java Code
CallableStatement stmt = conn.prepareCall("BEGIN rk_jscx(?, ?); END;");
stmt.registerOutParameter(1, OracleTypes.CURSOR);
stmt.registerOutParameter(2, Types.VARCHAR);
stmt.execute();
ResultSet rs = ((OracleCallableStatement)stmt).getCursor(1);
while (rs.next()) {
System.out.println(rs.getDate("sysdate"));
}
The above prints 2012-10-23
Check your jdbc driver as well

How to Pass datatable as input to procedure in C#?

I am wrote stored procedure to Insert data into database table but i am not getting how to pass datatable to stored procedure kindly tell how to use it.
below is my storedprocedure
CREATE OR REPLACE PROCEDURE PR_SREE_TEST(p_recordset In SYS_REFCURSOR) IS
Contrac_rc SREE_TEST%rowtype;
BEGIN
Loop
Fetch p_recordset Into Contrac_rc;
EXIT WHEN p_recordset%NOTFOUND;
Insert into SREE_TEST(CT,DESC,FLAG)
Values(Contrac_rc.CT,Contrac_rc.DESC,Contrac_rc.FLAG);
End Loop;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END PR_SREE_TEST;
/
and cs page
public DataSet sreetest(DataTable dt)
{
DataSet dsRegularIndentdtl = new DataSet();
try
{
OracleConnection OraConn = new OracleConnection(strDBConnection);
OraConn.Open();
OracleCommand OraCmd = new OracleCommand();
OraCmd.Connection = OraConn;
OraCmd.CommandText = "PR_SREE_TEST";
OraCmd.CommandType = CommandType.StoredProcedure;
OracleParameter parameter = new OracleParameter();
var recordSet1 = new DataTable();
recordSet1 = dt;
OraCmd.Parameters.Add("p_recordset", OracleDbType.RefCursor, recordSet1, ParameterDirection.Input);
OraCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
return dsRegularIndentdtl;
}
}
above is my code it is saying that p_recordset not valied. please tell me how to execute it.
Make sure you are using the correct overload of OraCmd.Parameters.Add(),
As per msdn the fourth parameter is not parameter direction, it is as below
public OracleParameter Add(
string parameterName,
OracleType dataType,
int size,
string srcColumn
)

Resources