Salesforce, accessing TargetObject fields from ProcessInstance object using SOQL - apex

I have the following in my controller for a visualforce page which is consumed by a PageBlockTable.
I can access other standard fields of the p.ProcessInstance.TargetObject such as p.ProcessInstance.TargetObject.Name and .Id etc...
But how can I access custom fields of TargetObject of where the record is related to? Or is this not possible? If its not possible then I assume I can do it in a seperate query, but I cannot figure out how.
Thank you
List<ProcessInstanceWorkitem> results = [Select p.ProcessInstance.Status, p.ProcessInstance.TargetObject.Name, p.ProcessInstance.TargetObject.Id, p.Actor.Name, p.CreatedBy.Name, p.CreatedDate FROM ProcessInstanceWorkitem p];

You have to perform an additional SOQL query on the TargetObject, as ProcessInstance is polymorphic. for example.
List<ProcessInstanceWorkitem> results = [Select p.ProcessInstance.Status, p.ProcessInstance.TargetObject.Name, p.ProcessInstance.TargetObject.Id, p.Actor.Name, p.CreatedBy.Name, p.CreatedDate FROM ProcessInstanceWorkitem p];
List<Id> targetObjectIds = new List<Id>();
for(SObject result : results)
{
targetObjectIds.add(result.p.ProcessInstance.TargetObject.Id);
}
List<SObject> targetObjectFields = [SELECT Id, Field names FROM SObject WHERE Id IN:targetObjectIds];
Edited:
Please change SObject to the object you are currently using.

Related

Copy Product Price into a Custom Field Object using APEX Trigger in Salesforce

Trying to just copy the Cost_Price__c field of a product into a custom object when it is updated (if possible inserted too) using an APEX trigger.
I'm so close but the error I am getting at the moment is: Illegal assignment from PricebookEntry to String
trigger updateAccount on Account (after update) {
for (Account oAccount : trigger.new) {
//create variable to store product ID
string productId = oAccount.Product__c;
//SQL statement to lookup price of product using productID
PricebookEntry sqlResult = [SELECT Cost_Price__c
FROM PricebookEntry
WHERE Product2Id =: productId];
//save the returned SQL result inside the field of Industry - Illegal assignment from PricebookEntry to String
oAccount.Industry = sqlResult;
}
}
Am I right in thinking it's because its returning a collective group of results from the SOQL call? I've tried using the sqlResult[0] which still doesn't seem to work.
The Illegal Assignmnet because you are assigning a whole Object i.e PriceBook Entry to a string type of field i.e Industry on Account.
Please use the following code for assignment.
oAccount.Industry = sqlResult[0].Cost_Price__c;
Please mark the answer if this works for you.
Thanks,
Tushar

How to avoiding AND condition if parameter is null in Spring Data JPA query

I am trying to get the result of one query using Spring Data JPA. Here I am sending some parameter and receiving result according to that.
My repository query is,
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByUsername(#Param("uname") String uname , #Param("pname") String pname );
And calling from controller like the following,
#RequestMapping(value = "/joinResult", method = RequestMethod.GET)
public List<Users> joinResultShow()
{
return (List<Users>) userRepo.findByUsername("test_user","testRole");
}
Here we can see that if I am passing some value then only checking according to that parameter. Here I need to modify my query like if parameter is null, then not need to use AND condition in query.
How can I modify this query for avoiding AND condition if parameter is null? I am new to Spring Data JPA world.
Here are some possible options for you
1. Create multiple methods in your repository like
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname AND p.pname = :pname")
List<Users> findByusernamewithRole(#Param("uname") String uname , #Param("pname") String pname );
#Query("select u.username,p.pname from Users u join u.priviJoin p where u.username = :uname")
List<Users> findByUsernameWithoutRole(#Param("uname") String uname);
Write a custom respository and use EntityManager. With this you can create a dynamic queries based on your input using CriteriaBuilder and use this criteria in querying.
Last and the most preferred option in case of dynamic inputs(like you have) is Querydsl.
Some articles about querydsl
http://www.baeldung.com/querydsl-with-jpa-tutorial
http://www.querydsl.com/static/querydsl/latest/reference/html/ch02.html

TypedQuery<x> returns vector of Object[] instead of list of x-type object

I have a method:
public List<Timetable> getTimetableTableForRegion(String id) {
List<Timetable> timetables;
TypedQuery<Timetable> query = em_read.createQuery("SELECT ..stuff.. where R.id = :id", Timetable.class).setParameter("id", Long.parseLong(id));
timetables = query.getResultList();
return timetables;
}
which returns this:
so, what am I missing in order to return a list of Timetable's?
ok, so, ..stuff.. part of my JPQL contained an inner join to other table. Even through in SELECT there were selected fields just from one table, which was used as type - Timetable, Eclipslink was unable to determine if this fields are part of that entity and instead of returning list of defined entity returned list of Object[].
So in conclusion: Use #OneToMany/#ManyToOne mappings (or flat table design) and query just for ONE table in your JPQL to be able to typize returned entities.
Not sure it might be something is looking for, but I had similar problem and converted Vector to ArrayList like this:
final ArrayList<YourClazz> results = new ArrayList<YourClazz>();;
for ( YourClazzkey : (Vector<YourClazz>) query.getResultList() )
{
results.add(key);
}
i have faced the same problem. and my entity has no one to one or one to many relationship. then also jpql was giving me queryresult as vector of objects. i changed my solution to query to criteria builder. and that worked for me.
code snippet is as below:
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Timetable> criteria = builder.createQuery(Timetable.class);
Root<Enumeration> root = criteria.from(Timetable.class);
criteria.where(builder.equal(root.get("id"), id));
List<Timetable> topics = this.entityManager.createQuery(criteria) .getResultList();
return topics;

Apex code to update new Opportunity with values from related object

What would be the proper method to update a list of new Opportunities with the values from a related record.
for (Opportunity opps:Trigger.new){
[SELECT Id, CorpOwner__r, Contact__r,(SELECT Id, AccountLocation from Account)]
o.CorpOwner__r =Account.Id; o.AccountLocation = opps.Account.AccountLocation;
insert opps
Do you call the lookup fields by the __r suffix? Could you do a before insert operation and still look up the Opportunity.CorpOwner__r relationship to values in the CorpOwner__r Account record, or does that relationship not exist since the record has not been created? What would be a proper batchified way to go about it?
Here's a possibility that demonstrates a number of concepts:
trigger UpdateOpptyWithAccountInfo on Opportunity (before insert) {
// Keep this SOQL query out of the FOR loop for better efficiency/batching
Map<Id, Account> relatedAccounts = new Map<Id, Account>(
[SELECT Id, AccountLocation__c
FROM Account
WHERE Id IN
(SELECT AccountId
FROM Opportunity
WHERE Id = :Trigger.new)
]
);
for (Opportunity o : Trigger.new) {
/* Find each opportunity's Account in the map we queried for earlier
* Note: there's probably a more efficient way to use a Map of Opportunity IDs to Account objects...
* This works fine and could be more readable.
*/
for (Account a : relatedAccounts.values()) {
if (a.Id == o.AccountId) {
// Once you've found the account related to this opportunity, update the values
o.CorpOwner__c = a.Id;
o.AccountLocation__c = a.AccountLocation__c;
}
}
}
// We're still inside an `insert` trigger, so no need to call `insert` again.
// The new fields will be inserted along with everything else.
}
If you're establishing the relationship between objects, use the __c suffix:
o.CorpOwner__c = a.Id; // Associate Account `a` as Opportunity `o`'s CorpOwner
If you're looking up a field on a related object, then you would use __r:
System.debug(o.CorpOwner__r.Name); // Print Opportunity `o`'s CorpOwner's name

Is there a way to update a database field based on a list?

Using JPA, I have a list of entries from my database :
User(id, firstname, lastname, email)
That I get by doing:
List<User> users = User.find("lastname = ?", "smith");
And I'd like to update all in one request, by doing something like this :
"UPDATE USER SET email = null IN :list"
and then set the parameter "list" to users
Is it possible? if so, how?
Thanks for your help :)
Well, you could embed the query that you used to obtain list in the where clause of the update.
UPDATE User a SET a.email = null
WHERE user IN (SELECT b FROM User b WHERE lastName = :?)
By doing this you'd be doing the query to search the list and the update in single update query.
How do you like that? Do you think this could work?
-EDIT-
Since you want to use the original list of items instead of a list just retrieved from the database, you can still ensure you build the original list like this
UPDATE User a SET a.email = null
WHERE user IN (SELECT b FROM User b WHERE lastName IN(:originalList))
Then when you invoke it, you can do something like this:
Collection<String> originalList = Arrays.asList("Kenobi", "Skywalker", "Windu");
query.setParameter("originalList", originalList);
By this, you can still ensure the query will only contain items in your original list and not any possible new item from the database, provided that that last name is a candidate key in the database, otherwise I would recommend that you use the ID for the subquery instend of the last name.
if you have jpa+hibernate you can use entityManager.createQuery() for creating hql query
like that:
String hql = "UPDATE Supplier SET name = :newName WHERE name IN :name";
entityManager.createQuery(hql);