I am doing the R&D on the duplicate error scenario in SF Bulk API and found that somehow I am not able to perform insert and update operation simultaneously for the contact with the same(external id) within the single batch.
I received a duplicate error. Screen capture for reference
https://www.screencast.com/t/ReE41vuzb
When the batch contains different external id's I do not have any error. But when external Id is repeated in a single batch I receive the below error.
{
"success" : false,
"created" : false,
"id" : null,
"errors" : [ {
"message" : "Duplicate external id specified: 7401",
"fields" : [ "Origami_ID__c" ],
"statusCode" : "DUPLICATE_VALUE",
"extendedErrorDetails" : null
}
Although there is No duplicate at the target side.
You just need the last record from multiple records with same unique id.
For this follow the below logic:
//Create Map and populate the map with last record having unique id
Map<String,MyObject__c> mapWithUniqueIdMyObject = new Map<String,MyObject__c>();
MyObject__c currentObject;
for(Integer currentPosition = myObjectListWith5000Records.size(); currentPosition >=0 ;currentPosition--){
currentObject = myObjectListWith5000Records.get( currentPosition );
if( !mapWithUniqueIdMyObject.containsKey(currentObject.Origami_ID__c) ){//If the map does not contain any object with unique id then put the object in the map
mapWithUniqueIdMyObject.put( currentObject.Origami_ID__c, currentObject );
}
}
upsert mapWithUniqueIdMyObject.getValues();
Related
I am trying to enter unique values to the Contact object. Here is the code:
List<Contact> conList = new List<Contact> {
new Contact(FirstName='Joe',LastName='Smith',Department='Finance'),
new Contact(FirstName='Kathy',LastName='Smith',Department='Technology'),
new Contact(FirstName='Caroline',LastName='Roth',Department='Finance'),
new Contact()};
// Caroline Roth already exists so I want this code to update her record, not insert another Caroline Roth record
Database.UpsertResult[] srList = Database.upsert(conList, Contact.Fields.Name, false);
Salesforce's documentation states
"The upsert statement matches the sObjects with existing records by comparing values of one field. If you don’t specify a field when calling this statement, the upsert statement uses the sObject’s ID to match the sObject with existing records in Salesforce. Alternatively, you can specify a field to use for matching. For custom objects, specify a custom field marked as external ID. For standard objects, you can specify any field that has the idLookup property set to true. For example, the Email field of Contact or User has the idLookup property set."
I have two questions:
1) how can we see which fields on the Contact object have their idLookup property set to true
2) why am I getting the error in the subject line when I execute the code?
1:
Map<String, Schema.SObjectField> contacFieldsMap = Schema.getGlobalDescribe().get('Contact').getDescribe().fields.getMap();
for (Schema.SObjectField field : contacFieldsMap.values()) {
Schema.DescribeFieldResult fieldResult = field.getDescribe();
if (fieldResult.isIdLookup()) System.debug(fieldResult.getName() + ' IS idLookup');
}
2: System.debug(Contact.Name.getDescribe().isIdLookup()); // false
I am inserting the data in bulk mode.I want to insert the data from one db table to another db table. I am using Scatter-gather message processor.I have 10 records in source db table, in this 10 records the second record has some invalid data (like firstname is null) remaining 9 records are valid data, but in my target db table firstname column is not null. While inserting these 10 records into target db, its throwing the error as firstname is not null. How to identify particular record has invalid data using exception handling in mule. I am new in mule esb. Can anyone help on this scenario.`
%output application/java
payload map
{
id : $.Id,
customerid : $.Customerid,
address : $.Address,
dob : $.Dob,
firstname : $.Firstname,
lastname : $.LastName,
middlename : $.Middlename,
phoneno : $.Phoneno,
batch : $.Batch,
recorddate : $.RecordDate
}]]>
`
Kindly post the exception message you are getting along with your xml flow.
But as of now i may give below suggestion.
Use a collection splitter to split and process each records.
catch the exception in the error handling block using the context #**[Exception.causedBy(your exception class)]**
After this kindly configure your strategy what to do in case of this exception happens.
In your case log your information with any column value or any record id that is unique for every message.This may help you out to see on which particular record your exception has occurred.
Thanks!
I am following Link to integrate cloudant no sql-db.
There are methods given create DB, Find all, count, search, update. Now I want to update one key value in one of my DB doc file. how Can i achieve that. Document shows like
updateDoc (name, doc)
Arguments:
name - database name
docID - document to update
but when i pass my database name and doc ID its throwing database already created can not create db. But i wanted to updated doc. So can anyone help me out.
Below is one of the doc of may table 'employee_table' for reference -
{
"_id": "0b6459f8d368db408140ddc09bb30d19",
"_rev": "1-6fe6413eef59d0b9c5ab5344dc642bb1",
"Reporting_Manager": "sdasd",
"Designation": "asdasd",
"Access_Level": 2,
"Employee_ID": 123123,
"Employee_Name": "Suhas",
"Project_Name": "asdasd",
"Password": "asda",
"Location": "asdasd",
"Project_Manager": "asdas"
}
So I want to update some values from above doc file of my table 'employee_table'. So what parameters I have to pass to update.
first of all , there is no concept named table in no sql world.
second, to update document first you need to get document based on any input field of document. you can also use Employee_ID or some other document field. then use database.get_query_result
db_name = 'Employee'
database = client.create_database(db_name,throw_on_exists=False)
EmployeeIDValue = '123123'
#here throw_on_exists=False meaning dont throw error if DB already present
def updateDoc (database, EmployeeIDValue):
results = database.get_query_result(
selector= { 'Employee_ID': {'$eq': EmployeeIDValue} }, )
for result in results:
my_doc_id = result["_id"]
my_doc = database[my_doc_id] #===> this give you your document.
'''Now you can do update'''
my_doc['Employee_Name'] = 'XYZ'
my_doc.save() ====> this command updates current document
Jdev Version : 11.1.1.7
I have created a Department VO based Department EO with the following query :
SELECT DeptEO.DEPARTMENT_ID,
DeptEO.DEPARTMENT_NAME,
DeptEO.MANAGER_ID,
DeptEO.LOCATION_ID,
DeptEO.ACTIVE
FROM DEPARTMENTS DeptEO where DeptEO.DEPARTMENT_ID > 250
UNION
SELECT 280 , 'Advertising',200,1700,'Y' from Dual
For the simplicity , I have used a sample statement from dual table , in real scenario , the query after UNION clause will populate from a table.
After running the query ,I get the result that is desired on the UI .
Now my requirement is to insert this newly created row with DEPARTMENT_ID as 280 , into DB table DEPARTMENTS.
While committing , ADF throws error as " oracle.jbo.RowAlreadyDeletedException: JBO-29114 " which is correct as the this row is missing from DB table , so when it goes for taking a lock on the row for update , it doesn't find anything .
Is there any way that i can instruct ADF to consider this row for Insert rather than update .
We also tried to populate the data of this row into a new row instance created from RowSetIterator , and afterwards remove the culprit row by calling removeFromCollection() and then inserting the duplicated row , but still no luck .
Other approaches that we are thinking of are :
1- Create another VO/EO and insert values in table through them .
2- Create a DB View for this query and trigger on this view , so when ever an update operation comes , we do our logic in trigger i.e. decide whether to update or insert the data.
Can you please guide what should be done in such scenario .
Regards,
Siddharth
Edit : Code for Inserting Row (What I was trying but it's not working)
RowSetIterator rsi=iterator.getRowSetIterator();
Row editableRow= rsi.createRow();
while(rsi.hasNext()){
Row r =rsi.next();
if((""+r.getAttribute("DepartmentId")).toString().equals("280") ){
System.err.println("? Equality row found!!!");
editableRow.setAttribute("DepartmentId", r.getAttribute("DepartmentId"));
editableRow.setAttribute("DepartmentName", r.getAttribute("DepartmentName"));
editableRow.setAttribute("ManagerId", r.getAttribute("ManagerId"));
editableRow.setAttribute("LocationId", r.getAttribute("LocationId"));
editableRow.setAttribute("Active", r.getAttribute("Active"));
rsi.removeCurrentRowFromCollection();
}
}
if(editableRow !=null){
System.err.println("? Row value after removal : "+editableRow.getAttribute("DepartmentName"));
rsi.insertRow(editableRow);
operBindingCommit.execute();
}
Your use case can be implemented in a couple of ways. First way is to iterate over row set in managed bean and check if department with id 280 exists, if yes then update the row otherwise invoke Create with parameters for department VO. The second way, and would say the better way, is to create a method for update/insert at business component level, either in ViewObjectImpl or in ApplicationModuleImpl and then invoke it from managed bean.
Here is the sample code for insert/update method written in VOImpl
public void updateInsertJobs(String jobId, String jobTitle,
String minSalary, String maxSalary)
{
RowSetIterator rSet = this.createRowSetIterator(null);
JobsViewRowImpl row = new JobsViewRowImpl();
Boolean jobExist = false;
if (null != jobId)
{
try
{
while (rSet.hasNext())
{
row = (JobsViewRowImpl) rSet.next();
if (row.getJobId().equals(jobId))
{
row.setJobTitle(jobTitle);
row.setMinSalary(new Number(minSalary));
row.setMaxSalary(new Number(maxSalary));
jobExist = true;
}
}
if (!jobExist)
{
JobsViewRowImpl r = (JobsViewRowImpl) this.createRow();
r.setJobId(jobId);
r.setJobTitle(jobTitle);
r.setMinSalary(new Number(minSalary));
r.setMaxSalary(new Number(maxSalary));
this.insertRow(r);
}
this.getDBTransaction().commit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Make sure to expose the method in Client Interface in order to be able to access it from data control.
Here is how to invoke the method from managed bean:
public void insertUpdateData(ActionEvent actionEvent)
{
BindingContainer bc =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding oB = bc.getOperationBinding("updateInsertJobs");
oB.getParamsMap().put("jobId", "TI_STF");
oB.getParamsMap().put("jobTitle", "Technical Staff");
oB.getParamsMap().put("minSalary", "5000");
oB.getParamsMap().put("maxSalary", "18000");
oB.execute();
}
Some references which could be helpful:
http://mahmoudoracle.blogspot.com/2012/07/adf-call-method-from-pagedefinition.html#.VMLYaf54q-0
http://adftidbits.blogspot.com//2014/11/update-vo-data-programatically-adf.html
http://www.awasthiashish.com/2012/12/insert-new-row-in-adf-viewobject.html
Your view object become readonly due to custom sql query.
However you still can create row in dept table using entity.
Create java implemetation including accessors for DeptEO.
Create custom method in view object and create new entity or update existing using entity definition there. To find that required row exist, you can check that entity with this key is already exists. Something like this (assuming deptId is your primary key):
public void createOrUpdateDept(BigInteger deptId){
DeptEOImpl dept;
EntityDefImpl deptDef = DeptEOImpl.getDefinitionObject();
Key key = new Key(new Object[]{deptId});
dept = deptDef.findByPrimaryKey(getDBTransaction(), key);
if (dept == null){
// Creating new entity if it doesn't exist
dept = deptDef.createInstance2(getDBTransaction(), null);
dept.setDepartmentId(deptId);
}
// Changing other attributes
dept.setDepartmentName("New name");
// Commiting changes and refreshing ViewObject if required
getDBTransaction().commit();
executeQuery();
}
This code is just a sample, use it as reference/idea, don't blindly copy/paste.
I have an existing datastore entity as below:
#Data
#Entity
public class Data
{
#Id #Index long id;
boolean expired;
}
I am in need to filter the data based on expired field, so I have to change the entity to have the filed expired now indexed. The modified entity is as below:
#Data
#Entity
public class Data
{
#Id #Index long id;
#Index boolean expired;
}
Below is the existing data in the datastore before the Index created:
Column : Data
id : 1
expired : true
id : 2
expired : false
id : 3
expired : false
My intention is to fetch the data using objectify with a filter on expired, so I have my code modified to use the below objectify quering:
return (List<Data>) ofy.load().type( Data.class ).filter( "expired = ", false ).list();
It is supposed to return two records, however it does return nothing.
BTW, after Index created, I added a new record into the entity as below
id : 4
expired : false
If I query back, I now see one result and that is with id = 4. Seems the filter works only on the newly added records and the index dint apply on all the old records? How to resolve this problem?
The reason the existing entities are not being returned is because they have not been indexed since you modified your entity class.The Objectify documentation states that:
Single property indexes are created/updated when you save an entity.
To get the existing existing entity instances to appear in your queries you will have to resave them, which will consequently force the Datastore to create their indexes.
You have to do the following for each existing entity:
Retrieve (load) the existing entity from the Datastore
Write (save) the existing entity back to the Datastore