A colleague has configured Java and MySQL to {send/receive} = [IN/OUT] parameters as HashMap and returns the result as HashMap.
Is it possible or any third party package required to configure?
public void sendValuesTODatabase(String user_id, String userName) {
HashMap hm1 = new HashMap();
hm1.put("1", user_id); // Parameters according to the Type
hm1.put("2", username);
int nooftable = 3; /* represents number of select statements used in Stored
Procedure */
Vector vCols = new Vector();
vCols.addElement("1"); // One Column used for selection in Mysql select query 1
vCols.addElement("2"); // Two Column used for selection in Mysql select query 2
vCols.addElement("1"); // one Column used for selection in Mysql select query 3
BlobValues bls = new BlobValues();
HashMap hmap = (HashMap)bls.getGeneric(hm1,"DB_SCHEMA_NAME.SP_PACKAGE_NAME.PROCEDURE_NAME",
nooftable, vCols);
HashMap dBResult1 = (HashMap)hmap.get("GENERICJAVA1"); // Select stmt result1 in HashMap
HashMap dBResult2 = (HashMap)hmap.get("GENERICJAVA2"); // Select stmt result2 in HashMap
HashMap dBResult3 = (HashMap)hmap.get("GENERICJAVA3"); // Select stmt result3 in HashMap
}
Spring Framework offers a solution for this scenario.
We can use org.springframework.jdbc.object.StoredProcedure or org.springframework.jdbc.core.simple.SimpleJdbcCall class and pass the input parameter Map to its execute() method.
It returns the output parameter Map which you can iterate.
Below is example of StoredProcedure Class.
#Component
public class ItemInsert extends StoredProcedure {
public static final String SPROC_NAME = "schema.oracle_pkg.proc_name";
public static final String INPUT_PARAM = "input_prm_name";
public static final String OUPUT_PARAM = "output_prm_name";
#Inject
public ItemInsert(DataSource ds) {
super(ds, SPROC_NAME);
declareParameter(new SqlParameter(INPUT_PARAM, Types.VARCHAR));
declareParameter(new SqlOutParameter(OUTPUT_PARAM, Types.NUMERIC));
compile();
}
public Item insert(Item item)
throws DataAccessException {
Map<String, Object> inputs = new HashMap<String, Object>();
inputs.put(INPUT_PARAM, item.getSomething());
Map<String, Object> output = super.execute(inputs);
Object newId = output.get(OUTPUT_PARAM);
if (newId != null) {
item.setId(Long.parseLong(newId.toString()));
}
return item;
}
Example of SimpleJdbcCall can be found at http://www.pretechsol.com/2014/04/how-to-call-stored-procedure-using.html#.VAtktsWSw1I
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(template)
.withProcedureName("customerDetails");
Map<String, Object> inParamMap = new HashMap<String, Object>();
inParamMap.put("id", 1);
SqlParameterSource in = new MapSqlParameterSource(inParamMap);
Map<String, Object> simpleJdbcCallResult = simpleJdbcCall.execute(in);
System.out.println(simpleJdbcCallResult);
Related
My problem is as follows:
My service loops over items that are passed as args. For each item, i make two calls. My first price call gives me 9999 which means nothing was returned. That's fine - that's possible. My stock call works perfectly and i get the correct stock value returned. On the second iteration, my price call returns the same value as the previous stock call.
So, i get 9999 for price, then 150 for stock, then 150 for price. What's throwing me is that the price out parm is 6th, whereas the stock out parm is 8th. No idea how it would retain that value in a different position.
It seems that my jdbctemplate isn't being cleared or it's storing previous out params. Here's the code involved:
MyService.java
#Service
public class MyService extends BaseService implements MyInterface{
protected static final Logger logger = LoggerFactory.getLogger(MyService.class);
#Autowired
private MyDAO myDAO;
public myResponse checkOrder(args...)
{
for(something in args){
// PRICE
// Grab price data
LinkedHashMap<String, Object> priceCallInParams = new LinkedHashMap<String, Object>();
priceCallInParams .put("param1", "param1val");
priceCallInParams .put("param2", "param2val");
priceCallInParams .put("param3", "param3val");
priceCallInParams .put("param4", "param4val");
priceCallInParams .put("param5", "param5val");
LinkedHashMap<String, Object> priceCallOutParams = new LinkedHashMap<String, Object>();
priceCallOutParams .put("price", "0");
logger.debug("Getting data...");
Map<String, Object> priceData = new HashMap<String, Object>();
priceData = myDAO.checkPrice(priceCallInParams , priceCallOutParams );
BigDecimal unitPrice = new BigDecimal(9999);
if (!priceData .get("PRCE").toString().trim().equals("")){
unitPrice = new BigDecimal(priceData.get("PRCE").toString().trim());
}
System.out.println("PRC - "+unitPrice);
// AVAILABLE STOCK
// Grab check stock data
LinkedHashMap<String, Object> checkStockInParms = new LinkedHashMap<String, Object>();
checkStockInParms.put("param1", "param1val");
checkStockInParms.put("param2", "param2val");
checkStockInParms.put("param3", "param3val");
checkStockInParms.put("param4", "param4val");
checkStockInParms.put("param5", "param5val");
checkStockInParms.put("param6", "param6val");
checkStockInParms.put("REQQTY", "123");
LinkedHashMap<String, Object> checkStockOutParms = new LinkedHashMap<String, Object>();
checkStockOutParms .put("AVAILQTY", "0");
checkStockOutParms .put("NEXTDUE"," ");
checkStockOutParms .put("NEXTQTY","0");
logger.debug("Getting data...");
Map<String, Object> checkStockDat = new HashMap<String, Object>();
checkStockDat = myDAO.checkStock(checkStockInParms , checkStockOutParms );
// Output quantity
int AvailQTY = Integer.valueOf(checkStockDat.get("AVAILQTY").toString().trim());
if (reqBIT.getRequestedQuantity()>AvailQTY) {
resBIT.setConfirmedQuantity(AvailQTY);
}
else {
resBIT.setConfirmedQuantity(reqBIT.getRequestedQuantity());
}
}
}
}
MyDAO.java
#Component
public class MyDAO extends BaseDAO{
protected static final Logger logger = LoggerFactory.getLogger(OrderDAO.class);
public Map<String, Object> checkStock(LinkedHashMap<String, Object> inparms, LinkedHashMap<String, Object> outparms){
StringBuilder builtSQL = new StringBuilder();
builtSQL.append("CALL ");
builtSQL.append("checkstock ");
// just generates our param string (?,?,?...)
builtSQL.append(DataUtilities.genParmPlaceholderStringFromTotal(inparms.size()+outparms.size()));
return executeStoredProcedure(builtSQL.toString(), inparms, outparms);
}
public Map<String, Object> checkPrice(LinkedHashMap<String, Object> inparms, LinkedHashMap<String, Object> outparms){
logger.debug("CheckPrcc Initiated");
StringBuilder builtSQL = new StringBuilder();
builtSQL.append("CALL ");
builtSQL.append("checkprice ");
// just generates our param string (?,?,?...)
builtSQL.append(DataUtilities.genParmPlaceholderStringFromTotal(inparms.size()+outparms.size()));
return executeStoredProcedure(builtSQL.toString(), inparms, outparms);
}
}
BaseDAO.java
public class BaseDAO{
#Autowired
protected JdbcTemplate jdbcTemplate;
protected static final Logger logger = LoggerFactory.getLogger(BaseDAO.class);
protected Map<String, Object> executeStoredProcedure(String SQL, LinkedHashMap<String, Object> inParams, LinkedHashMap<String, Object> outParams){
Map<String, Object> result = new HashMap<String, Object>();
List<SqlParameter> declaredParameters = new ArrayList<SqlParameter>();
for (Map.Entry<String, Object> entry : inParams.entrySet()) {
declaredParameters.add(new SqlParameter(entry.getKey().toString(), Types.CHAR));
}
for (Map.Entry<String, Object> entry : outParams.entrySet()) {
declaredParameters.add(new SqlOutParameter(entry.getKey().toString(), Types.CHAR));
}
result = jdbcTemplate.call(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection connection)
throws SQLException {
CallableStatement callableStatement = connection.prepareCall(SQL);
int index = 0;
for (Map.Entry<String, Object> entry : inParams.entrySet()) {
index++;
callableStatement.setString(index, entry.getValue().toString());
}
for (Map.Entry<String, Object> entry : outParams.entrySet()) {
index++;
callableStatement.registerOutParameter(index, Types.CHAR);
}
return callableStatement;
}
}, declaredParameters);
return result;
}
}
My service is invoked from my rest controller, which pass the args (if that matters).
I've been racking my brain and can't find any information regarding this issue. I'm new to spring boot and Java. I don't believe i'm doing something too egregious.
In our situation, this was being caused our i-series. If no data is present to return, the system still returns 10 chars from memory - being the last value it just returned. The solution is to always populate the return value to clear the memory.
Not spring-boot after all!
I've done plenty of research on figuring out a way to return a result set using the Spring JDBC framework. I am new to Spring and I'm working on an implementation that calls a stored function that uses multiple input parameters and returns a ref cursor, but I can't seem to figure out the proper way of doing this. The code that I have now keeps returning an empty array. Can someone suggest to me what would be the best way of handling this?
Here's some of my code snippets:
public class StandardRodsDAOImplementation implements StandardRodsDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
private final String schema_name = "xxlt";
private final String procedure_catalog = "xxlt_bpg_std_width_pkg";
private final String procedure_name = "get_std_rods";
public List<StandardRods> getDefaultRodMatAndColor(String series, String style, String material, String color)
{
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withSchemaName(schema_name).withCatalogName(procedure_catalog).withFunctionName(procedure_name)
.declareParameters(new SqlOutParameter("lref", OracleTypes.CURSOR,
new StandardRodsMapper()),
new SqlParameter("p_series_ind", Types.VARCHAR),
new SqlParameter("p_style_ind", Types.VARCHAR),
new SqlParameter("p_material_ind", Types.VARCHAR),
new SqlParameter("p_color_ind", Types.VARCHAR));
simpleJdbcCall.compile();
Map<String, Object> inParams = new HashMap<>();
inParams.put("p_series_ind", Types.VARCHAR);
inParams.put("p_style_ind", Types.VARCHAR);
inParams.put("p_material_ind", Types.VARCHAR);
inParams.put("p_color_ind", Types.VARCHAR);
Map output = simpleJdbcCall.execute(inParams);
return (List) output.get("lref"); }
Mapper function:
public class StandardRodsMapper implements RowMapper<StandardRods> {
public StandardRods mapRow(ResultSet rs, int rowNum) throws SQLException
{
StandardRods standardRods = new StandardRods();
standardRods.setSeries(rs.getString("SERIES_IND"));
standardRods.setStyle(rs.getString("BELT_STYLE_IND"));
standardRods.setMaterial(rs.getString("MATERIAL_IND"));
standardRods.setColor(rs.getString("COLOR_IND"));
return standardRods;
}}
Interface:
public interface StandardRodsDAO {
List<StandardRods> getDefaultRodMatAndColor(String series, String style, String material, String color);}
Junit Test:
#Configuration
#ComponentScan
public class SpringDemoTestingApplication
{
StandardRodsDAOImplementation standardRodsDAOImplementation;
#Before
public void setUp()
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"spring-call-proc-simplejdbccall.xml");
standardRodsDAOImplementation = (StandardRodsDAOImplementation) applicationContext.getBean("standardRodsDao");
}
#Test
public void testGetStandardRod()
{
List<StandardRods> standardRods = standardRodsDAOImplementation.getDefaultRodMatAndColor("550", "TIGHT TRANSFER FLAT TOP", "NYLON", "DARK BROWN");
System.out.println(standardRods);
}
Procedure:
FUNCTION get_std_rods (p_series_ind IN varchar2, p_style_ind IN varchar2, p_material_ind IN varchar2, p_color_ind IN varchar2)
return SYS_REFCURSOR IS lref SYS_REFCURSOR;
BEGIN
OPEN lref FOR
SELECT bbv.default_rod_mat, bbv.default_rod_color
FROM xxlt.xxlt_bpg_belt_val bbv
WHERE bbv.series_ind = p_series_ind AND
bbv.belt_style_ind = p_style_ind AND
bbv.material_ind = p_material_ind AND
bbv.color_ind = p_color_ind;
RETURN lref;
END;
public List<UMRDTO> getDocumentLink(Session session)
{
List<UMRDTO> documentationList = null;
Query query = null;
query = session.createQuery(UMRSQLInt.DOCUMENTATION_LIST);
documentationList = query.list();
return documentationList;
}
Whenever I restart my app all the hashmap are empty and no data is present that in inputed earlier
I need to get the list i.e objectName , objectType and the documentationLink from the above query and then put the data (objectName,documentationLink) in the HashMap if the objectName is Domainname then the data to be put in domainDocumentationMap or if it is combo then in domainComboDocumentationMap
private static Map<String, String> domainDocumentationMap = null;
private static Map<String, String> domainComboDocumentationMap = null;
static
{
domainDocumentationMap = new HashMap<String, String>();
domainComboDocumentationMap = new HashMap<String, String>();
}
public static Map<String, String> getDomainDocumentationMap(){
return domainDocumentationMap;
}
public static void setDomainDocumentationMap(String objectName, String documentationLink) {
MMTUtil.domainDocumentationMap.put(objectName, documentationLink);
}
what query shall i write?
#RequestMapping("/regressionTest")
public String home(Model model, #ModelAttribute CleanupTitles cleanupTitles) {
applicationToEnvStatus = MappingUtil
.getApplicationToEnvStatusMapping(databaseOperation);
model.addAttribute("parameters", new Parameters());
model.addAttribute("cleanupTitle", cleanupTitles);
cleanupTitles.setTitles(databaseOperation.getTitle());
return "home";
}
MappingUtil class
public class MappingUtil {
private enum Environment {
dev, stage, prod
}
private static Map<String, String> applicationToStatus;
private static Map<String, List<String>> applicationToEnvStatus;
public static Map<String,List<String>> getApplicationToEnvStatusMapping(
DatabaseOperation databaseOperation) {
applicationToStatus = new HashMap<String, String>();
applicationToEnvStatus = new HashMap<String, List<String>>();
for (Environment e : Environment.values()) {
System.out.println(e.toString());
applicationToStatus = databaseOperation
.getApplicationToEnvMapping(e.toString());
for (Map.Entry<String, String> entry : applicationToStatus
.entrySet()) {
List<String> li = new ArrayList<String>();
li.add(e.toString());
li.add(entry.getValue());
applicationToEnvStatus.put(entry.getKey(), li);
}
//System.out.println(e.toString() + " " + applicationToStatus);
}
System.out.println(applicationToEnvStatus);
return applicationToEnvStatus;
}
Database call
public Map<String, String> getApplicationToEnvMapping(String envName) {
String sqlQuery = "select application_name,is_completed from (select application_name,is_completed from rtf_run_status where env='"
+ envName + "' order by date_created desc) where rownum<=3";
Map<String, String> applicationToStatus = new HashMap<String, String>();
jdbcTemplate.query(sqlQuery, new ResultSetExtractor<Map>() {
#Override
public Map extractData(ResultSet rs) throws SQLException,
DataAccessException {
while (rs.next()) {
applicationToStatus.put(rs.getString("application_name"),
rs.getString("is_completed"));
}
return applicationToStatus;
}
});
return applicationToStatus;
}
The controller is making 2 db calls to: a) MappingUtil.getApplicationToEnvStatus() and b) cleanupTitles.setTitles(). This results in view taking a lot of time to load. The result set returned from each query is around 4-5.
What would be the best approach to load view at a faster response time? Should I execute db calls in a new Thread or is there any better way of doing this?
I want to create a HashMap for hive's "show table extended" output.I am trying below approach
JavaRDD<HashMap<String,String>> hiveOutput = hiveContext.sql("show table extended like sourcing_trg_tbl").toJavaRDD().map(new Function<String, Map<String,String>>() {
#Override
public Map<String,String> call(String row) throws Exception {
return splitStringToMap(row);
}
private Map<String,String> splitStringToMap(String s) {
String[] fields = s.toString().split(Pattern.quote(":"), -1);
Map<String,String> hiveMap = new HashMap<String,String>();
hiveMap.put(fields[0], fields[1]);
return hiveMap;
}
});
Map<String,String> hiveOutputMap = hiveOutput.collect();
While .map I am getting below error:
The method map(Function<Row,R>) in the type AbstractJavaRDDLike<Row,JavaRDD<Row>> is not applicable for the arguments (new Function<String,Map<String,String>>(){})
Is it not possible to return a Java Map through this approch?