Ibatis out params from stored procedure in Oracle 11g - java

I have a stored procedure which has three out params all user defined types.
I use ibatis as ORM from java code to call the stored procedure.
How do i configure this stored procedure call in ibatis xml
and how do I get the results back in my java code.
procedure test(
p_a in int default 0 ,
p_b in number default 0,
p_criteria out TBL_A,
p_baseline out TBL_B,
p_results out TBL_C);
Any help would be highly appreciated.
thanks,
gagan suri

In your xml configuration provide parameters with in/out mode (jdbcType is optional):
<procedure id="callProcedure1" parameterClass="map">
{
call procedure1(
#value1,jdbcType=DECIMAL,mode=INOUT#,
#value2,jdbcType=DECIMAL,mode=INOUT#,
#value3,jdbcType=DECIMAL,mode=INOUT#,
)
}
</procedure>
And in your dao class just get your results from parameters:
final Map<String, Object> params = new HashMap<String, Object>();
//provide input parameters here
params.put("value1", 1);
AbstractSQLMapDao.queryForObject("namespace.callProcedure1", params);
//retrieve you output
Double value1 = params.get("value1")

Related

How can I get springboot transaction'data in jooq query

So I have a problem in jooq about getting data in spring-boot transaction.
I use a transaction to save the base data, and then I want to use jooq to get these data. But I found that what I fetched is null.
String sql = dslContext.select().from(Tables.SALES_INVENTORY).getSQL();
System.out.println(sql);
Result<Record> fetch1 = dslContext.select().from(Tables.SALES_INVENTORY).fetch();
System.out.println(fetch1);
String groupbySql =
dslContext
.select(Tables.SALES_INVENTORY.ITEM_ID, sum(Tables.SALES_INVENTORY.ON_HAND_QTY))
.from(Tables.SALES_INVENTORY)
.groupBy(Tables.SALES_INVENTORY.ITEM_ID)
.getSQL();
System.out.println(groupbySql);
Result<Record2<UUID, BigDecimal>> fetch =
dslContext
.select(Tables.SALES_INVENTORY.ITEM_ID, sum(Tables.SALES_INVENTORY.ON_HAND_QTY))
.from(Tables.SALES_INVENTORY)
.groupBy(Tables.SALES_INVENTORY.ITEM_ID)
.fetch();
System.out.println(fetch);
List<SalesInventoryEntity> all = salesInventoryRepository.findAll();
all.forEach(s -> System.out.println(s));
Jooq's SQL is correct, but can't find and data return as if I use JPA #Transactional to do my test method. And I use jpa-repository to get data, it found the right data.
So my main problem is how can I get the right data in JPA transactional?
Here is what I used to init the base data. It's a test method, and its class is #Transactional, so this means that the method is also #Transactional?
public void initSalesInventories() {
List<SalesInventoryEntity> salesInventories = Lists.newArrayList();
ItemEntity itemEntity = itemRepository.findById(itemId1).get();
int i = 0;
for (StockLocationEntity stockLocationEntity : stockLocationEntities) {
SalesInventoryEntity salesInventoryEntity = new SalesInventoryEntity();
salesInventoryEntity.setStockLocation(stockLocationEntity);
salesInventoryEntity.setSalesOrganization(usSalesOrgEntity);
salesInventoryEntity.setItem(itemEntity);
salesInventoryEntity.setItemClass(ItemClass.SALEABLE);
salesInventoryEntity.setOnHandQty(100);
salesInventoryEntity.setReservedQty(0);
salesInventoryEntity.setAvailableQty(100);
salesInventoryEntity.setLeadTime(5);
DocumentType[] values = DocumentType.values();
salesInventoryEntity.setDocType(values[i % 7]);
String code = "TO-201906112010000" + i;
i++;
salesInventoryEntity.setDocCode(code);
salesInventories.add(salesInventoryEntity);
}
salesInventoryRepository.saveAll(salesInventories);
}
After init my base data, I used jooq to read the data, and find nothing. I don't know whether jooq can't read other transaction's data or jooq just read the actual data from the database. If you know something about it please give me some advices.

Neo4j OGM FilteredQueryBuilder

Anyone has use class FilteredQueryBuilder to create a Cypher query in Java?
I'm trying to create this query using neo4j-ogm:
MATCH (n:Message) WHERE n.messageContext = 'RECEBER_BOLETO_EM_ABERTO'
MATCH (n)-[r0:NEXT]->(m) WHERE r0.response = 'SIM'
return m
Map<String, Object> parameters = new HashedMap<>();
parameters.put("messageContext", "RECEBER_BOLETO_EM_ABERTO");
parameters.put("response", "SIM");
Filters filtersNode = new Filters();
Filter filterStartNode = new Filter("messageContext", ComparisonOperator.EQUALS, "RECEBER_BOLETO_EM_ABERTO");
filterStartNode.setNestedEntityTypeLabel("Message");
filterStartNode.setNestedPropertyName("messageContext");
filterStartNode.setRelationshipDirection(Relationship.OUTGOING);
filterStartNode.setBooleanOperator(BooleanOperator.AND);
filtersNode.add(filterStartNode);
Filter filterEndNode = new Filter("response", ComparisonOperator.EQUALS, "SIM");
filterEndNode.setNestedPropertyName("response");
filterEndNode.setRelationshipDirection(Relationship.TYPE);
filterEndNode.setBooleanOperator(BooleanOperator.AND);
filtersNode.add(filterEndNode);
FilteredQuery fq = FilteredQueryBuilder.buildRelationshipQuery("NEXT", filtersNode);
fq.setReturnClause("return m");
The Builder class doesn't parse the parameters into cypher query and throw the exception as follow:
org.neo4j.ogm.exception.CypherException: Error executing Cypher; Code:
Neo.ClientError.Statement.ParameterMissing; Description: Expected a
parameter named messageContext_messageContext_0
Thanks in advance.
The query builders are internal classes to OGM. Don't rely on them, they could change in the future. The use of Filters with the OGM session is fine though.
To build custom cypher queries, you might be interested by Cypher DSL.

What is the best way to pass multiply parameters as one http query parameter?

I have java web application (servlet) that does user authentication using SalesForce Server OAuth Authentication Flow. This OAuth Authentication provides "state" query parameter to pass any data on callback. I have a bunch of parameters that I want to pass through this "state" query param. What is the best way to do it? In java in particularly?
Or in other words, what is the best way to pass an array or map as a single http query parameter?
You can put all in json or xml format or any other format and then encode in base64 as a one large string. Take care that params can impose some hard limit on some browser/web server.
So, I have done it this way. Thank you guys! Here are some code snippets to illustrate how it works for me:
// forming state query parameter
Map<String, String> stateMap = new HashMap<String, String>();
stateMap.put("1", "111");
stateMap.put("2", "222");
stateMap.put("3", "333");
JSONObject jsonObject = new JSONObject(stateMap);
String stateJSON = jsonObject.toString();
System.out.println("stateJSON: " + stateJSON);
String stateQueryParam = Base64.encodeBase64String(stateJSON.getBytes());
System.out.println("stateQueryParam: " + stateQueryParam);
// getting map from state query param
ObjectMapper objectMapper = new ObjectMapper();
stateMap = objectMapper.readValue(Base64.decodeBase64(stateQueryParam.getBytes()), LinkedHashMap.class);
System.out.println("stateMap: " + stateMap);
Here is output:
stateJSON: {"1":"111","2":"222","3":"333"}
stateQueryParam: eyIxIjoiMTExIiwiMiI6IjIyMiIsIjMiOiIzMzMifQ==
stateMap: {1=111, 2=222, 3=333}

Spring StoredProcedure Optional Parameters

I have a procedure in Oracle that has 12 total parameters and 3 optional. How can I account for these optional parameters if I'm using the StoredProcedure object in Spring 3.1.0?
Here's what I have so far in my StoredProcedure class
public Map<String, Object> execute(Evaluation evaluation) {
Map<String, Object> input_params = new HashMap<String, Object>();
input_params.put(COURSE_MAIN_PK1_INPUT_PARAM, evaluation.getCourseId());
input_params.put(USERS_PK1_INPUT_PARAM, evaluation.getUsersPk1());
input_params.put(ACCREDITATION_PK1_INPUT_PARAM, evaluation.getAccreditationPk1());
input_params.put(TYPE_PK1_INPUT_PARAM, evaluation.getTypePk1());
input_params.put(PRIVACY_TYPE_PK1_INPUT_PARAM, evaluation.getPrivacyTypePk1());
input_params.put(FORM_TYPE_PK1_INPUT_PARAM, evaluation.getFormTypePk1());
input_params.put(TITLE_INPUT_PARAM, evaluation.getTitle());
input_params.put(DESCRIPTION_INPUT_PARAM, evaluation.getDescription());
if(evaluation.getStartDate() != null) {
input_params.put(START_DATE_INPUT_PARAM, new java.sql.Date(evaluation.getStartDate().getMillis()));
}
if(evaluation.getEndDate() != null) {
input_params.put(END_DATE_INPUT_PARAM, new java.sql.Date(evaluation.getEndDate().getMillis()));
}
input_params.put(SAVE_TO_GRADECENTER_INPUT_PARAM, evaluation.getGradeCenterColumn());
input_params.put(CREATE_ANNOUNCEMENT_INPUT_PARAM, evaluation.getAnnouncement());
return super.execute(input_params);
}
The problem with this is that I'm supplying 12 parameters and if the start and end dates are null, now I'm supplying 10 and getting an exception.
The default values for the dates in the database is null.
JDBC's PreparedStatement provides a facility to set null values to parameters using the setNull method. So, as long as you pass all the parameters to the stored procedure if they are null, Spring would be able to prepare the statement and execute it.
So, you needed to add the input parameters whose values are null, to the Map that is sent to the stored procedure call.
input_params.put(START_DATE_INPUT_PARAM,
(null != evaluation.getStartDate()
? new java.sql.Date(evaluation.getStartDate().getMillis())
: null));
The same would apply to END_DATE_INPUT_PARAM as well.

Stored Procedure returning multiple tables to spring jdbc template

Iam calling a stored procedure from my Spring DAO class using JdbcTemplate. My problem is that, stored procedure returns multiple tables. Is there a way to access multiple tables using Spring JdbcTemplate.
If I use
jdbcTemplate.queryForList(myStoredProc, new Object[]{parameters}
iam getting only first table from the result.
My database is SQL Server 2005.
Is there any method other than jdbcTemplate for my requirement?
The solution sinha referenced didn't work for me. I was able to solve this using JdbcTemplate#call(CallableStatementCreator, List<SqlParameter>). For example:
private static final String sql = "{call schema_name.the_stored_procedure(?, ?, ?)}";
// The input parameters of the stored procedure
private static final List<SqlParameter> declaredParams = Arrays.asList(
new SqlParameter("nameOfFirstInputParam", Types.VARCHAR),
new SqlParameter("nameOfSecondInputParam", Types.VARCHAR),
new SqlParameter("nameOfThirdInputParam", Types.VARCHAR));
private static final CallableStatementCreatorFactory cscFactory
= new CallableStatementCreatorFactory(sql, declaredParams);
// The result sets of the stored procedure
private static final List<SqlParameter> returnedParams = Arrays.<SqlParameter>asList(
new SqlReturnResultSet("nameOfFirstResultSet", SomeRowMapper.INSTANCE),
new SqlReturnResultSet("nameOfSecondResultSet", SomeOtherRowMapper.INSTANCE));
public static Map<String, Object> call(JdbcTemplate jdbcTemplate,
String param0,
String param1,
String param2) {
final Map<String, Object> actualParams = new HashMap<>();
actualParams.put("nameOfFirstInputParam", param0);
actualParams.put("nameOfSecondInputParam", param1);
actualParams.put("nameOfThirdInputParam", param2);
CallableStatementCreator csc = cscFactory.newCallableStatementCreator(actualParams);
Map<String, Object> results = jdbcTemplate.call(csc, returnedParams);
// The returned map will including a mapping for each result set.
//
// {
// "nameOfFirstResultSet" -> List<SomeObject>
// "nameOfSecondResultSet" -> List<SomeOtherObject>
// }
//
// For this example, we just return the heterogeneous map. In practice,
// it's better to return an object with more type information. In other
// words, don't make client code cast the result set lists. Encapsulate
// that casting within this method.
return results;
}
See http://static.springsource.org/spring/docs/2.0.7/reference/jdbc.html#jdbc-StoredProcedure
The example given in this section is exactly for your case where the stored procedure returns multiple result-sets. Although the example given there is for Oracle, but it should work in the same way for MS SQL Server also.

Categories