Does OnConflictStrategy.REPLACE work the same for Update and Insert? - android-room

We have the following legacy code
interface BaseDao<T> {
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrReplace(data: T): Single<Long>
#Update(onConflict = OnConflictStrategy.REPLACE)
fun update(data: T): Single<Long>
}
Do the functions would achieve the same results?
While I'm sure what #Insert(onConflict = OnConflictStrategy.REPLACE) based on my general SQL knowledge
Replace/ update records if found
Insert records if not found

Update will not insert records (rows) not found if you code or omit OnConflictStrategy.REPLACE. Update can only act upon rows that exist as per
It is not an error if the WHERE clause does not evaluate to true for any row in the table - this just means that the UPDATE statement affects zero rows. https://sqlite.org/lang_update.html

Related

Getting max value on server (Entity Framework)

I'm using EF Core but I'm not really an expert with it, especially when it comes to details like querying tables in a performant manner...
So what I try to do is simply get the max-value of one column from a table with filtered data.
What I have so far is this:
protected override void ReadExistingDBEntry()
{
using Model.ResultContext db = new();
// Filter Tabledata to the Rows relevant to us. the whole Table may contain 0 rows or millions of them
IQueryable<Measurement> dbMeasuringsExisting = db.Measurements
.Where(meas => meas.MeasuringInstanceGuid == Globals.MeasProgInstance.Guid
&& meas.MachineId == DBMatchingItem.Id);
if (dbMeasuringsExisting.Any())
{
// the max value we're interested in. Still dbMeasuringsExisting could contain millions of rows
iMaxMessID = dbMeasuringsExisting.Max(meas => meas.MessID);
}
}
The equivalent SQL to what I want would be something like this.
select max(MessID)
from Measurement
where MeasuringInstanceGuid = Globals.MeasProgInstance.Guid
and MachineId = DBMatchingItem.Id;
While the above code works (it returns the correct value), I think it has a performance issue when the database table is getting larger, because the max filtering is done at the client-side after all rows are transferred, or am I wrong here?
How to do it better? I want the database server to filter my data. Of course I don't want any SQL script ;-)
This can be addressed by typing the return as nullable so that you do not get a returned error and then applying a default value for the int. Alternatively, you can just assign it to a nullable int. Note, the assumption here of an integer return type of the ID. The same principal would apply to a Guid as well.
int MaxMessID = dbMeasuringsExisting.Max(p => (int?)p.MessID) ?? 0;
There is no need for the Any() statement as that causes an additional trip to the database which is not desirable in this case.

How to skip update when parameter is null/0 in spring batch with JdbcBatchItemWriter

We have a scenario wherein while doing a batch update on a table using JdbcBatchItemWriter, We are not finding a way to not update is the attribute is null. We don't want to have too many queries and ItemPreparedStatementSetter so we have a single query to update all fields in the table. Different batch jobs set update different attributes of the table
List<Report> summaryList = getSummaryList()
JdbcBatchItemWriter<ItemMktDcGpReport> writer1 = new JdbcBatchItemWriter<>();
String sql_update = GenericConstants.UPDATE_QUERY;
writer1.setDataSource(dataSource);
ItemPreparedStatementSetter<Report> updatePreparedStatementSetter = new ItemMergeUpdatePreparedItemSetter();
writer1.setItemPreparedStatementSetter(updatePreparedStatementSetter);
writer1.setSql(sql_update);
writer1.afterPropertiesSet();
writer1.write(summaryList);
Tried the following seeing few examples on conditional update at the query but it doesn't help yet.
Below is the query. Any help on this will be very much appreciated.
UPDATE_QUERY = "update [dbo].[test_tbl]
SET test_col1 = CASE When ?!=0 then ?
else test_col1 end ,
test_col2 = CASE When ?!=0 then ?
else test_col2 WHERE market=? and country = ?"
I don't want to construct the SQL query based on parameter as I will lose out on the bulk writing feature of JdbcBatchItemWriter. Can someone please suggest the right approach to solve this problem and possibly correct the SQL query I'm writing?

Hibernate select query: only want to know existence [duplicate]

This question already has an answer here:
HQL Query to check whether table has data or not
(1 answer)
Closed 7 years ago.
I need only the existence information of a record. I don't need the actual count. If there is a row (record) respect to the "where" condition, I will know that it exists.
If I write
select count(m) from MyEntity m where m.someProperty=1
it will count all the records and if there are many records, it may take long time and it will give me the information which I don't need actually.
How do I get the existence of a records with Hibernate HQL?
I found this one as best for me:
public Boolean existsOrNot (DTOAny i) {
Query q = getSession().
createQuery("select 1 from DTOAny t where t.key = :key");
q.setString("key", i.getKey() );
return (q.uniqueResult() != null);
}
from:
HQL Query to check whether table has data or not

Salesforce bulkify code - is this not already bulkified?

We have a class in salesforce that is called form a trigger. When using Apex Data Loader this trigger throws an error oppafterupdate: System.LimitException: Too many SOQL queries: 101
I commented out a line of code that calls the following static method in a class we wrote and there are no more errors with respect to the governing limit. So I can verify the method below is the culprit.
I'm new to this, but I know that Apex code should be bulkified, and DML (and SOQL) statements should not be used inside of loops. What you want to do is put objects in a collection and use DML statements against the collection.
So I modified the method below; I declared a list, I added Task objects to the list, and I ran a DML statement on the list. I commented out the update statement inside the loop.
//close all tasks linked to an opty or lead
public static void closeTasks(string sId) {
List<Task> TasksToUpdate = new List<Task>{}; //added this
List<Task> t = [SELECT Id, Status, WhatId from Task WHERE WhatId =: sId]; //opty
if (t.isEmpty()==false) {
for (Task c: t) {
c.Status = 'Completed';
TasksToUpdate.add(c); //added this
//update c;
}
}
update TasksToUpdate; //Added this
}
Why am I still getting the above error when I run the code in our sandbox? I thought I took care of this issue but apparently there is something else here? Please help.. I need to be pointed in the right direction.
Thanks in advance for your assistance
You have "fixed" the update part but the code still fails on the too many SELECTs.
We would need to see your trigger's code but it seems to me you're calling your function in a loop in that trigger. So if say 200 Opportunities are updated, your function is called 200 times and in the function's body you have 1 SOQL... Call it more than 100 times and boom, headshot.
Try to modify the function to pass a collection of Ids:
Set<Id> ids = trigger.newMap().keyset();
betterCloseTasks(ids);
And the improved function could look like this:
public static void betterCloseTasks(Set<Id> ids){
List<Task> tasksToClose = [SELECT Id
FROM Task
WHERE WhatId IN :ids AND Status != 'Completed'];
if(!tasksToClose.isEmpty()){
for(Task t : tasksToClose){
t.Status = 'Completed';
}
update tasksToClose;
}
}
Now you have 1 SOQL and 1 update operation no matter whether you update 1 or hundreds of opportunities. It can still fail on some other limits like max 10000 updated records in one transaction but that's a battle for another day ;)

NHibernate IQueryable doesn't seem to delay execution

I'm using NHibernate 3.2 and I have a repository method that looks like:
public IEnumerable<MyModel> GetActiveMyModel()
{
return from m in Session.Query<MyModel>()
where m.Active == true
select m;
}
Which works as expected. However, sometimes when I use this method I want to filter it further:
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.ID < 100
select new { m.Name };
Which produces the same SQL as the first one and the second filter and select must be done after the fact. I thought the whole point in LINQ is that it formed an expression tree that was unravelled when it's needed and therefore the correct SQL for the job could be created, saving my database requests.
If not, it means all of my repository methods have to return exactly what is needed and I can't make use of LINQ further down the chain without taking a penalty.
Have I got this wrong?
Updated
In response to the comment below: I omitted the line where I iterate over the results, which causes the initial SQL to be run (WHERE Active = 1) and the second filter (ID < 100) is obviously done in .NET.
Also, If I replace the second chunk of code with
var models = MyRepository.GetActiveMyModel();
var filtered = from m in models
where m.Items.Count > 0
select new { m.Name };
It generates the initial SQL to retrieve the active records and then runs a separate SQL statement for each record to find out how many Items it has, rather than writing something like I'd expect:
SELECT Name
FROM MyModel m
WHERE Active = 1
AND (SELECT COUNT(*) FROM Items WHERE MyModelID = m.ID) > 0
You are returning IEnumerable<MyModel> from the method, which will cause in-memory evaluation from that point on, even if the underlying sequence is IQueryable<MyModel>.
If you want to allow code after GetActiveMyModel to add to the SQL query, return IQueryable<MyModel> instead.
You're running IEnumerable's extension method "Where" instead of IQueryable's. It will still evaluate lazily and give the same output, however it evaluates the IQueryable on entry and you're filtering the collection in memory instead of against the database.
When you later add an extra condition on another table (the count), it has to lazily fetch each and every one of the Items collections from the database since it has already evaluated the IQueryable before it knew about the condition.
(Yes, I would also like to be the extensive extension methods on IEnumerable to instead be virtual members, but, alas, they're not)

Resources