how not to insert more than two sequential nextval value? - spring

I'm using spring framework and oracle DB for the Web solution system.
The problem is when I call the web page related on oracle sequence,
sometimes more than two rows are inserted on the DB table.
That rows has not duplicated values but increased values from sequence.
Also I already checked the java code,
but I didn't use the loop or for sentences or call twice insert sentences.
Is that occurred often?
and how can I solve the problem?
Do I have to add the code for checking value or make the oracle trigger on the table?
This is the code.
public void insertDefaultLParameter(HttpServletRequest request, String workflowId) throws Exception{
String newLParaId = mapper.getNewLParaId();
HashMap<String, String> condition = new HashMap<String, String>();
condition.put("newLParaId", newLParaId);
condition.put("paraValue", "2013-05");
condition.put("workflowId", workflowId);
mapper.insertLParameter(condition);
mapper.insertLParameterMapping(condition);
}
"getNewLParaId()" called the sequence "MT_L_PARA_MAPPING_SEQ" like the below sql.
SELECT 'LPARA' || LPAD(MT_L_PARA_MAPPING_SEQ.nextval,10,0) FROM DUAL
After getting the value, the value is inserted into two tables through "insertLParameter" and "insertLParameterMapping" mapping id.
And the below is the code which call "insertDefaultLParameter" class.
See the bottom of the code.
You can find "rfmService.insertDefaultLParameter(request, praWfId);".
#RequestMapping(value="/insertWorkflowInfo", method=RequestMethod.POST, headers="Accept=application/json")
public ModelAndView insertWorkflowDetail(Locale locae, Model model, HttpServletRequest request) throws Exception{
HttpSession session = request.getSession(false);
User user = (User)session.getAttribute("user");
String userId = user.getUserId();
String workflowNm = "";
String alsPpsCd = "";
String workflowDesc = "";
String pid = "";
String plevel = "";
if(request.getParameter("workflowNm") != null || !request.getParameter("workflowNm").equals("")) workflowNm = request.getParameter("workflowNm");
if(request.getParameter("alsPpsCd") != null || !request.getParameter("alsPpsCd").equals("")) alsPpsCd = request.getParameter("alsPpsCd");
if(request.getParameter("workflowDesc") != null || !request.getParameter("workflowDesc").equals("")) workflowDesc = request.getParameter("workflowDesc");
if(request.getParameter("pid") != null || !request.getParameter("pid").equals("")) pid = request.getParameter("pid");
if(request.getParameter("plevel") != null || !request.getParameter("plevel").equals("")) plevel = request.getParameter("plevel");
//0.
//HashMap<String,String> treeMgtInfo = new HashMap<String,String>();
//treeMgtInfo.put("treeId",pid);
//
HashMap<String,String> input = new HashMap<String,String>();
//2.
String praWfId = wfService.selectPraWfid();
input.put("praWfId", praWfId);
input.put("wfNm",workflowNm);
input.put("wfDesc", SecurityUtil.removeXSS(workflowDesc));
input.put("alsPpsCd",alsPpsCd);
input.put("usrId",userId);
input.put("rgUsrId",userId);
// 1.
wfService.insertWorkflowDetail(input);
input.put("treeNm",workflowNm);
//
int treeLevCd = new Integer(plevel) +1 ;
input.put("treeLevCd",""+treeLevCd);
input.put("treeBjCd",Constant.TREE_BJ_CD_WORKFLOW);
input.put("treeCd",Constant.TREE_CD_WORKFLOW);
//
input.put("treeLrkRufId",praWfId);
input.put("upTreeId",pid);
//
int sceXrsSeqVl = treeService.selectSceXrsSeqId(input);
input.put("sceXrsSeqVl",""+sceXrsSeqVl);
String treeId = treeService.selectTreeIdInfo();
input.put("treeId",treeId);
// 2.
rfmService.insertDefaultLParameter(request, praWfId);
// 3.
treeService.insertTreeMgtInfoWithId(input);
ModelAndView modelAndView=new ModelAndView("defaultViews");
modelAndView.addObject("treeId",treeId);
modelAndView.addObject("praWfId",praWfId);
return modelAndView;
}
This is all of code related on the sequence.

Related

First initialization of a VisitCount session gives a null pointer exception but a redeploy makes it work

When I initially start the tomcat Server I get a nullpointer exception referring to the line "visitCount = visitCount + 1;" And I'm not quite sure how to fix it. To my understanding it has something to do with the fact that when the session is new and it does not know what value to give back although I thought it would give 0 because of this line "Integer visitCount = new Integer(0);"
Redeploying makes the nullpointerexception go away. So that to me confirms my assumption explained above.
Help is greatly appreciated.
Error
Servlet:
private String getLogCount(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
Date createTime = new Date(session.getCreationTime());
Date getLastAccesTime = new Date(session.getLastAccessedTime());
String titleKey;
Integer visitCount = new Integer(0);
String visitCountKey = new String("visitCount");
if (session.isNew()) {
titleKey = "Welkom!";
} else {
titleKey = "Welkom terug!";
visitCount = (Integer) session.getAttribute(visitCountKey);
visitCount = visitCount + 1;
}
session.setAttribute(visitCountKey, visitCount);
session.setAttribute("createTime", createTime);
session.setAttribute("lastAccessTime", getLastAccesTime);
session.setAttribute("title", titleKey);
return "activiteit.jsp";
}
JSP PAGE:
<h1 class="explanation">${title}</h1>
<table>
<tr>
<th>Aantal keren deze website bezocht: ${visitCount}</th>
<th>Eerste moment van je sessie: ${createTime}</th>
<th>Laatste moment van je sessie: ${lastAccessTime}</th>
</tr>
</table>
[..] although I thought it would give 0 because of this line Integer visitCount = new Integer(0);
That line of code ends up doing nothing because a few lines below you override it with this:
visitCount = (Integer) session.getAttribute(visitCountKey);
So now, visitCount has whatever value you extract from the session. Based on the error you are describing, you most likely retrieve null from the session.
So basically, your code does this:
Integer visitCount = new Integer(0); // value is 0
// ...
visitCount = (Integer) session.getAttribute(visitCountKey); // value is whatever you get from session, most likely null based on the error you get
visitCount = visitCount + 1; // this can result in null + 1, thus your error
I would rewrite the code like this:
private String getLogCount(HttpServletRequest request, HttpServletResponse response) {
HttpSession session = request.getSession();
Date createTime = new Date(session.getCreationTime());
Date getLastAccesTime = new Date(session.getLastAccessedTime());
String titleKey;
int visitCount = 0;
String visitCountKey = "visitCount";
if (session.isNew()) {
titleKey = "Welkom!";
} else {
titleKey = "Welkom terug!";
Integer sessionVisitCount = (Integer) session.getAttribute(visitCountKey);
if (sessionVisitCount != null) {
visitCount = sessionVisitCount.intValue() + 1;
}
}
session.setAttribute(visitCountKey, Integer.valueOf(visitCount));
session.setAttribute("createTime", createTime);
session.setAttribute("lastAccessTime", getLastAccesTime);
session.setAttribute("title", titleKey);
return "activiteit.jsp";
}

Pageable sorting with specifications returns duplicated results

I have a Service entity that has a field Jobs which has Job entity in a ManyToMany relationship.
Filtering, sorting and pagination works perfectly, but the only problem is sorting by Jobs.
When I send a request to /serviceslist?sort=jobs&sortDir=asc I get duplicate results for each Service that has multiple jobs connected to it. To be more specific, if a Service has 4 jobs, the service gets returned 4 times and so on.
I think I should use groupBy, but how would I implement groupBy in my service below?
Service:
public Page<com.bitweb.syda.data.entity.service.Service> getServicesList(ServiceListRequest request, Pageable pageable) {
Specification<com.bitweb.syda.data.entity.service.Service> spec = where(null);
if (request.getSearch() != null) spec = spec.and(search(request.getSearch()));
if (request.getName() != null) spec = spec.and(name(request.getName()));
if (request.getJobs() != null) spec = spec.and(hasJobs(request.getJobs()));
if (request.getNeedsPatrol() != null) spec = spec.and(needsPatrol(request.getNeedsPatrol()));
return serviceRepository.findAll(spec, pageable);
}
Controller:
#RequestMapping(path = "/serviceslist", method = RequestMethod.GET)
public Page<ServiceResponse> getServicesList(
#RequestParam(defaultValue = "0") Integer page,
#RequestParam(defaultValue = "10") Integer size,
#RequestParam(required = false) String search,
#RequestParam(required = false) String name,
#RequestParam(required = false) String jobs,
#RequestParam(required = false) Boolean needsPatrol,
#RequestParam(defaultValue = "createTime") String sort,
#RequestParam(defaultValue = "asc") String sortDir
) {
ServiceListRequest request = new ServiceListRequest(search, name, jobs, needsPatrol);
Sort.Direction direction;
if (sortDir.equals("asc")) {
direction = Sort.Direction.ASC;
} else {
direction = Sort.Direction.DESC;
}
return serviceService.getServicesList(request, of(page, size, direction, sort))
.map(ServiceResponse::new);
}
Here are some examples what I've tried already:
public Page<com.bitweb.syda.data.entity.service.Service> getServicesList(ServiceListRequest request, Pageable pageable) {
Specification<com.bitweb.syda.data.entity.service.Service> spec = (root, query, builder) -> {
//you can do any check here if you want with the join and check all the search parameters here if you want
//Join<Object, Object> jobs = root.join("jobs");
// also set query to get distinct values
query.distinct(true);
return null;
};
if (request.getSearch() != null) spec = spec.and(search(request.getSearch()));
if (request.getName() != null) spec = spec.and(name(request.getName()));
if (request.getJobs() != null) spec = spec.and(hasJobs(request.getJobs()));
if (request.getNeedsPatrol() != null) spec = spec.and(needsPatrol(request.getNeedsPatrol()));
return serviceRepository.findAll(spec, pageable);
}
After trying this everything works as expected, but sorting by jobs gives me this error:
PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
Position: 652
I'm not very proficient with SQL and Criteria API and I don't know what I could do to fix this.
When using query.groupBy(root); instead of distinct, I get this error:
PSQLException: ERROR: column "job4_.id" must appear in the GROUP BY clause or be used in an aggregate function
Position: 780

Adding a variable value in endpoint URL

I am trying pass contact id as a parameter to one of the webservices and get value to update in account object. But i am not able to set contact records ID field as a parameter in end point URL.
List<Contact> ContactUpdate = [SELECT id FROM Contact where Rep__c like 'CRM%'];
String ContactID;
HttpRequest req = new HttpRequest();
req.setTimeout(60000);
req.setHeader('Accept','*/*');
req.setHeader('Content-Type','application/json'); // Content Type
req.setMethod('GET');
for (Contact c : ContactUpdate)
{
ContactID = c.id;
req.setEndpoint('https://xxx/xxxx/xxxxx/xxx/xxx-lookup? ContactID= {! ContactID});
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
JSONParser parser = JSON.createParser(res.getBody());
String GMMID;
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'GCGMM')) {
// Get the value.
parser.nextToken();
// Compute the grand total price for all invoices.
GMMID = parser.gettext();
}
}
//ContactUpdate.IsFutureContext__c = true;
C.Group_ID__c = GMMID;
update c;
}
Could someone please guide me in adding variable as parameter in endpoint URL.
Try using the body and removing it from your endpoint.
String body = 'ContactID=' + contactID;
req.setbody(body);

Hextoraw() not working with IN clause while using NamedParameterJdbcTemplate

I am trying to update certain rows in my oracle DB using id which is of RAW(255).
Sample ids 0BF3957A016E4EBCB68809E6C2EA8B80, 1199B9F29F0A46F486C052669854C2F8...
#Autowired
private NamedParameterJdbcTemplate jdbcTempalte;
private static final String UPDATE_SUB_STATUS = "update SUBSCRIPTIONS set status = :status, modified_date = systimestamp where id in (:ids)";
public void saveSubscriptionsStatus(List<String> ids, String status) {
MapSqlParameterSource paramSource = new MapSqlParameterSource();
List<String> idsHexToRaw = new ArrayList<>();
String temp = new String();
for (String id : ids) {
temp = "hextoraw('" + id + "')";
idsHexToRaw.add(temp);
}
paramSource.addValue("ids", idsHexToRaw);
paramSource.addValue("status", status);
jdbcTempalte.update(*UPDATE_SUB_STATUS*, paramSource);
}
This above block of code is executing without any error but the updates are not reflected to the db, while if I skip using hextoraw() and just pass the list of ids it works fine and also updates the data in table. see below code
public void saveSubscriptionsStatus(List<String> ids, String status) {
MapSqlParameterSource paramSource = new MapSqlParameterSource();]
paramSource.addValue("ids", ids);
paramSource.addValue("status", status);
jdbcTempalte.update(UPDATE_SUB_STATUS, paramSource);
}
this code works fine and updates the table, but since i am not using hextoraw() it scans the full table for updation which I don't want since i have created indexes. So using hextoraw() will use index for scanning the table but it is not updating the values which is kind of weird.
Got a solution myself by trying all the different combinations :
#Autowired
private NamedParameterJdbcTemplate jdbcTempalte;
public void saveSubscriptionsStatus(List<String> ids, String status) {
String UPDATE_SUB_STATUS = "update SUBSCRIPTIONS set status = :status, modified_date = systimestamp where id in (";
MapSqlParameterSource paramSource = new MapSqlParameterSource();
String subQuery = "";
for (int i = 0; i < ids.size(); i++) {
String temp = "id" + i;
paramSource.addValue(temp, ids.get(i));
subQuery = subQuery + "hextoraw(:" + temp + "), ";
}
subQuery = subQuery.substring(0, subQuery.length() - 2);
UPDATE_SUB_STATUS = UPDATE_SUB_STATUS + subQuery + ")";
paramSource.addValue("status", status);
jdbcTempalte.update(UPDATE_SUB_STATUS, paramSource);
}
What this do is create a query with all the ids to hextoraw as id0, id1, id2...... and also added this values in the MapSqlParameterSource instance and then this worked fine and it also used the index for updating my table.
After running my new function the query look like : update
SUBSCRIPTIONS set status = :status, modified_date = systimestamp
where id in (hextoraw(:id0), hextoraw(:id1), hextoraw(:id2)...)
MapSqlParameterSource instance looks like : {("id0", "randomUUID"),
("id1", "randomUUID"), ("id2", "randomUUID").....}
Instead of doing string manipulation, Convert the list to List of ByteArray
List<byte[]> productGuidByteList = stringList.stream().map(item -> GuidHelper.asBytes(item)).collect(Collectors.toList());
parameters.addValue("productGuidSearch", productGuidByteList);
public static byte[] asBytes(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}

HBase Aggregation

I'm having some trouble doing aggregation on a particular column in HBase.
This is the snippet of code I tried:
Configuration config = HBaseConfiguration.create();
AggregationClient aggregationClient = new AggregationClient(config);
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("drs"), Bytes.toBytes("count"));
ColumnInterpreter<Long, Long> ci = new LongColumnInterpreter();
Long sum = aggregationClient.sum(Bytes.toBytes("DEMO_CALCULATIONS"), ci , scan);
System.out.println(sum);
sum returns a value of null.
The aggregationClient API works fine if I do a rowcount.
I was trying to follow the directions in http://michaelmorello.blogspot.in/2012/01/row-count-hbase-aggregation-example.html
Could there be a problem with me using a LongColumnInterpreter when the 'count' field was an int? What am I missing in here?
You can only use long(8bytes) to do sum with default setting.
Cause in the code of AggregateImplementation's getSum method, it handle all the returned KeyValue as long.
List<KeyValue> results = new ArrayList<KeyValue>();
try {
boolean hasMoreRows = false;
do {
hasMoreRows = scanner.next(results);
for (KeyValue kv : results) {
temp = ci.getValue(colFamily, qualifier, kv);
if (temp != null)
sumVal = ci.add(sumVal, ci.castToReturnType(temp));
}
results.clear();
} while (hasMoreRows);
} finally {
scanner.close();
}
and in LongColumnInterpreter
public Long getValue(byte[] colFamily, byte[] colQualifier, KeyValue kv)
throws IOException {
if (kv == null || kv.getValueLength() != Bytes.SIZEOF_LONG)
return null;
return Bytes.toLong(kv.getBuffer(), kv.getValueOffset());
}

Resources