spring boot + hibernate Can I use entityMnager.persist(item) after I get the item with named query? - spring

I am using spring boot and hibernate. I have a named query where I select an item. Then I want to set some property and then to make entityManager.persist() or entityManager.merge(). Can I do this or the instance of my item will be unmanaged after the named query and persist/merge will fail ?
Here is my code where em.persist() actually do not work:
public String getSMSText(String sourceUrl) {
Rss rss;
List urls = em.createNamedQuery("Rss.getFeedByUrl").setParameter("url", sourceUrl).getResultList();
if (urls.size() != 0) {
rss = (Rss) urls.get(urls.size() - 1);
for (Rss.Item item : rss.getChannel().getItems()) {
try {
if (Utils.isToday(item.getPubDateAsDate()) && !item.isPushed()) {
item.setPushed(true);
em.refresh(item);
em.persist(item);
return item.getTitle() + "." + item.getSummary();
}
} catch (ParseException e) {
logger.info("Cannot parse pub date", e);
}
}
logger.info(sourceUrl + " No news for today!");
return null;
}
return null;
}

My guess is that your change on the item will not have any effect.
You should change your item only when the query transaction is completely closed.
I think you have two way:
1- Change your code to update your entity only when you are sure that the select query transaction was closed.
2- Use EntityManager.refresh() on your item, after the named query and before change and persist it.

Related

How to query relational data using subclasses? parse.com and Unity

Im trying to query all elements of subclass in Unity. I have found SDK constraint or missing something here.
According to documentation querying subclasses is possible.
> var query = new ParseQuery<Armor>()
.WhereLessThanOrEqualTo("rupees", ((Player)ParseUser.CurrentUser).Rupees);
query.FindAsync().ContinueWith(t =>
{
IEnumerable<Armor> result = t.Result;
});
Im however using relation table and cannot specify
Here is my code:
IEnumerator LoadMyDesigns(Action<RequestResult> result) {
ParseUser user = ParseUser.CurrentUser;
ParseRelation<Design> relation = user.GetRelation<Design>("designs");
Task<IEnumerable<Design>> task = relation.Query.FindAsync();
while (!task.IsCompleted) yield return new WaitForEndOfFrame();
if (task.IsFaulted) {
//error
foreach(var e in task.Exception.InnerExceptions) {
ParseException parseException = (ParseException) e;
Debug.LogError("Error message " + parseException.Message);
Debug.LogError("Error code: " + parseException.Code);
result(new RequestResult(true, parseException.Message));
}
}
else {
result(new RequestResult(true, new List<Design>(task.Result)));
}
}
And error:
ArgumentNullException: Must specify a ParseObject class name when creating a ParseQuery.
So the question is how do I specify query subclass type when using relations?
Thanks.
I've struggled with the same problem and in my case I needed to provide the propertyName again in de GetRelationProperty call.
For example:
[ParseFieldName("designs")]
public ParseRelation<Design> Designs
{
get { return GetRelationProperty<Design>("Designs"); }
}
Try querying your designs Table.
Make a new query for class "Designs" where equal("owner", PFUser.currentUser())
This should return all of the designs for the current User.

How can i dynamically Create Criteria Mongodb Spring data mongo Template

I need to dynamically create a criteria but i am having problem how can i build criteria dynamically.
I need exactly the same as in here Build dynamic queries with Spring Data MongoDB Criteria but i am getting an error while i am converting my Criteria list to a toArray as its keep saying that orCriteria does not have support for Criteria[]
here is my effort so far
Here is my query structure
{
"query":{
"where":[{
"or":[
{
"fieldName":"title","fieldValue":"Demo Event NEW YORK IIII22222",
"operator":"equal"
},
{
"fieldName":"createdBy","fieldValue":"system",
"operator":"equal"
}
]
}
]
}
}
and here is my parsing it to create criteria
if(null != eventSearch.getQuery())
{
if(null != eventSearch.getQuery().getWhere() && eventSearch.getQuery().getWhere().size()> 0)
{
for (Where whereClause : eventSearch.getQuery().getWhere()) {
if(null != whereClause.getOr() && whereClause.getOr().size() > 0){
for (Field field: whereClause.getOr()) {
if(field.getOperator().equalsIgnoreCase(QueryOperator.IS))
{
// So i need to append an or Condition to main query for each or object in my query can anyone tell me how can i achieve this?
query.addCriteria(Criteria.where(whereClause.getFieldName()).gte(whereClause.getFieldValue()));
}
}
}
}
}
I need to pass my all where clauses with in or object to orOperator function as a parameter
Criteria c = new Criteria().orOperator(Need to pass my where clauses here);
Better use an ArrayList of Criteria to keep $or criteria as below.
List<Criteria> orCriteriaList = new ArrayList<Criteria>();
for (Field field: whereClause.getOr()) {
if(field.getOperator().equalsIgnoreCase(QueryOperator.IS)){
Criteria c1 = Criteria.where(whereClause.getFieldName()).gte(whereClause.getFieldValue());
orCriteriaList.add(c1);
}
}
Then build the main query from this orCriteriaList as
mainQuery.addCriteria(new Criteria().orOperator(orCriteriaList.toArray(new Criteria[orCriteriaList.size()])));

How to handle jpa entity

I have a table client and from retrieving results I use this way
public ClientParent getClient(Long clientId,Long parentId){
String queryString="SELECT cp FROM Client cp where cp.cid.id=:clientId " +
"and cp.pid.id=:parentId ";
Query query=entityManagerUtil.getQuery(queryString);
query.setParameter("clientId", clientId);
query.setParameter("parentId", parentId);
return (ClientParent)query.getSingleResult();
}
This is the DAO method.
Actually for getting client at 1st control goes to controller class then to service and then DAO class
Now lets say that the client table is empty so in this case return (ClientParent)query.getSingleResult(); will throw me error.
I can handle this in by wrting in try catch block in service class as well as in controller class.But wanted to know if I can do with out throwing any exception.I mean do I have change the query or what should I return so that it will never throw exception even if the table is empty
you can use the getResultList() method
public ClientParent getClient(Long clientId,Long parentId){
String queryString="SELECT cp FROM Client cp where cp.cid.id=:clientId " +
"and cp.pid.id=:parentId ";
Query query=entityManagerUtil.getQuery(queryString);
query.setParameter("clientId", clientId);
query.setParameter("parentId", parentId);
List<ClientParent> result = query.getResultList();
if (result != null && result.size() >0){
return result.get(0);
} else {
return null;
}
}
I suggest you to surround your code with try-catch block. So will sure that the data is correct.
try {
// ... your code goes here
// getSingleResult()
return XXX;
} catch(NonUniqueResultException e) {
// here you know there is some bad data
// so you can ignore it or do something
} catch(NoResultException e){
return null;
}

Many-To-Many Entity Framework Update

I have an object that has a many-to-many relationship with another object. I am trying to write an update statement that doesn't result in having to delete all records from the many-to-many table first.
My data is:
StoredProcedure - StoredProcedureId, Name
Parameter - ParameterId, Name
StoredProcedure_Parameter - StoredProcedureId, ParameterId, Order
I have a UI for updating a stored procedured object (adding/removing parameters or changing the order of the parameters).
When I save, I end up at:
var storedProcedure = context.Sprocs.FirstOrDefault(s => s.SprocID == sproc.StoredProcedureId);
if (storedProcedure == null)
{
//do something like throw an exception
} else
{
storedProcedure.Name = sproc.Name;
//resolve Parameters many to many here
//remove all Params that are not in sproc.Params
//Add any params that are in sproc.Params but not in storedProcedure.Params
//Update the Order number for any that are in both
}
I know I could simply call .Clear() on the table and then reinsert all of the values with their current state (ensuring that all parameters that were removed by the UI are gone, new ones are added, and updated Orders are changed). However, I feel like there must be a better way to do this. Do many-to-many updates with EF usually get resolved by deleting all of the elements and reinserting them?
Here there is my code that I use and it works. The difference is that instead o having your 3 tables( StoredProcedure, StoredProcedure_Parameter and Parameter ) I have the following 3 tables: Order, OrdersItem(this ensure the many-to-many relation) and Item. This is the procedure that I used for updating or add an order, or after I change an existing OrderItem or add a new one to the Order.
public void AddUpdateOrder(Order order)
{
using (var db = new vitalEntities())
{
if (order.OrderId == 0)
{
db.Entry(order).State = EntityState.Added;
}
else
{
foreach (var orderItem in order.OrdersItems)
{
if (orderItem.OrderItemsId == 0)
{
orderItem.Item = null;
if (order.OrderId != 0)
orderItem.OrderId = order.OrderId;
db.Entry(orderItem).State = EntityState.Added;
}
else
{
orderItem.Order = null;
orderItem.Item = null;
db.OrdersItems.Attach(orderItem);
db.Entry(orderItem).State = EntityState.Modified;
}
}
db.Orders.Attach(order);
db.Entry(order).State = EntityState.Modified;
}
SaveChanges(db);
}
}

Update object in foreach loop

I am using EF4/LINQ for the first time and have run into an issue. I am looping thru the results of a LINQ query using a foreach loop as follows:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
CallOutcomeSubmission los = new CallOutcomeSubmission();
client = connectToService();
try
{
using (var context = new CallOutcomeContext())
{
// List of available actions
private static string ACTION_CALL_ATTEMPT = "Call Attempt";
DateTime oneDayAgo = DateTime.Now.AddHours(-24);
var query = from co in context.T_MMCallOutcome
join ca in context.T_Call on co.CallID equals ca.CallID
join lv in context.T_LeadVendorEmailHeader on co.LeadVendorEmailID equals lv.LeadVendorEmailID
where co.EnteredOn > oneDayAgo && co.MMLeadActionID == null
select new
{
co.CallOutcomeID,
co.CallID,
co.LeadVendorEmailID,
MMLeadID = lv.email_text,
ca.OutcomeID,
lv.FranchiseNumber,
co.MMLeadActionID,
co.LeadAction
};
// if any results found for query
if (query.Any())
{
foreach (var call in query.ToList())
{
// if the franchise exists
if (client.FranchiseExists(int.Parse(call.FranchiseNumber)))
{
switch (call.OutcomeID)
{
case 39: // Not Answered
call.LeadAction = ACTION_CALL_ATTEMPT;
break;
case 43: // Remove from Call List
break;
default: // If the OutcomeID is not identified in the case statement
break;
} // switch
}
else
{
los.eventLog.WriteEntry("CallOutcomeSubmission.OnTimedEvent: No franchise found with franchise ID " + call.FranchiseNumber);
}
// Save any changes currently on context
context.SaveChanges();
} // foreach
}
// if no results found from query write system log stating such
else
{
los.eventLog.WriteEntry("CallOutcomeSubmission.OnTimedEvent: No new entries found");
}
} // using
client.Close();
}
catch (System.TimeoutException exception)
{
los.eventLog.WriteEntry("CallOutcomeSubmission.OnTimedEvent:" + exception.ToString());
client.Abort();
}
catch (System.ServiceModel.CommunicationException exception)
{
los.eventLog.WriteEntry("CallOutcomeSubmission.OnTimedEvent:" + exception.ToString());
client.Abort();
}
}
When I try to do the assignment:
call.LeadAction = ACTION_CALL_ATTEMPT;
I get a build error of
Property or indexer 'AnonymousType#2.LeadAction' cannot be assigned to -- it is read only
I can't seem to find anything on this specific error doing a Google search and am not sure what I am doing wrong. Is it because the original query contains a join?
How can I do the assignment of call.LeadAction within the foreach loop?
I would also like to know if there are design issue withe way I have written the query or performed any of the operations since this is my first foray into EF/LINQ.
You're creating a new anonymous type - with the Linq joins and then trying to set that value. What you're really wanting to do, is update the call's LeadAction correct?
How would EF know to translate your new query back to an entity so it can go back to the database? It would have to go through alot of hoops, and it's not capable of that.
What you could do, is retrieve the Call from your database and set the LeadAction that way - I'm using Find, assuming that CallID is your PK:
case 39: // Not Answered
var thisCall = context.T_Call.Find(call.CallID)
thisCall.LeadAction = ACTION_CALL_ATTEMPT;
break;

Resources