Spring bulk update fields with id's matching the given list - sql

I need to do multiple updates in my DB based on the provided id.Right now I am iterating the id List and calling the update function of my repository again and again.However this is not efficient.I want to know if there is a way I can do bulk updates in one rest call by passing the id List and the other new field value list as parameter.Thanks in advance for the help.
Right now I'm calling this method again and again to update the values.However this is not at all efficient:
#Transactional
#Modifying
#Query("UPDATE Student c SET c.rollNo= :rollNo WHERE c.id = :id")
void updateStudentRollNo(#Param("id") long id, #Param("rollNo") String rollNo);

If you have the Student entities where you call the method updateStudentRollNo, you may call repository.saveAll(students) , that will make the updates on list. The way you are trying to do is not possible, because each student have a different rollNo, so batch update like that can't be done.

Related

Read from table, infer counter and insert on database using entity framework 5 and mvc 4

I have this situation. I have a table called Request. This table has a column named Number. Every time I want to insert a new Request then I fetch the last request and based on its Request Number I infer a new one.
For example, I have on my database Request1 with number 0001 then when I will insert a new one I fetch Request1 and based on its Number I infer my new Request Number which should be 0002.
The problem occurs when I want to create two Requests simultaneously. Process one fetch the Request1 and process two also gets Request1. When process one infers the new request number, which should be 0001, process two do the same. At the end I will create two new requests with the same Number.
Someone knows how to solve this?
Sorry about my english! ;)
There are several ways to solve your problem.
The field is always numeric, sequential, and each record the value must be higher than the last record?
If it is, you simply let the database do the work for you. Just set the field in question as the primary key of the table and how identity. In this case the database will provide the solution to internal competition, and of course to prevent ending up getting duplicate records. And the number is automatically filled by the DBMS (SQL Server, MySQL, Oracle ...)
If you are using EntityFramework and Code First, just go in the declaration of the entity (a C # class that defines the table in the database) and locate the field you need and add 2 attributes to him:
// Probably you have this kind of code (which fieldID should be the field name)
public Int32 fieldID {get; set;}
// Just add these two attributes before the declaration of the field
[Key]
[DatabaseGenerated (DatabaseGeneratedOption.Identity)]
public Int32 fieldID {get; set;}
/* Example in C#, assuming you are using SQL Server and EFCF */
/* EF CF means Entity Framework Code First! */
You need to implement a logic to populate this field, which may not be as described above, or the field is not numeric or can not be done by the database and have to be direct by your application?
You can implement a lock on straightforward piece of code that can not have competition.
In the class that makes the manipulation of data and you are encountering the problem declare a variable of type Object, static and read-only like this:
private static readonly Object concurrencyLock = new Object ();
In the method that implements the logic that needs to be accessed uniquely enclose the code with a lock policy
lock(concurrencyLock) {
//Do stuff here without concurrency
/* When the current request into this part of the code,
any other request will execute until the line above with "lock" statement.
Until this current request exit this "lock" block of code,
the other(s) will wait. As this one leave this block, one other join...
One at a time as you wish. */
}
There are others ways to do that too, but is a bit more complex or dosen't work well in a Web Application (like a Mutex, that would work fine if it's a Windows Service, ou Windows Form application)

Duplicate a record and its references in web2py

In my web2py application I have a requirement to duplicate a record and all its references.
For example
one user has a product (sponserid is the user). and this product has so many features stored in other tables (reference to product id).
And my requirement is if an another user is copying this product, the a new record will generate in the product table with new productid and new sponserid. And all the reference table records will also duplicate with the new product id. Effectively a duplicate entry is creating in all the tables only change is product id and sponserid.
The product table fields will change. So I have to write a dynamic query.
If I can write a code like below
product = db(db.tbl_product.id==productid).select(db.tbl_product.ALL).first()
newproduct = db.tbl_product.insert(sponserid=newsponserid)
for field,value in product.iteritems():
if field!='sponserid':
db(db.tbl_product.id==newproduct).update(field=value)
But I cannot refer a field name like this in the update function.
Also I would like to know if there is any other better logic to achieve this requirement.
I would greatly appreciate any suggestions.
For the specific problem of using the .update() method when the field name is stored in a variable, you can do:
db(db.tbl_product.id==newproduct).update(**{field: value})
But an easier approach altogether would be something like this:
product = db(db.tbl_product.id==productid).select(db.tbl_product.ALL).first()
product.update(sponserid=newsponserid)
db.tbl_product.insert(**db.tbl_product._filter_fields(product))
The .update() method applied to the Row object updates only the Row object, not the original record in the db. The ._filter_fields() method of the table takes a record (Row, Storage, or plain dict) and returns a dict including only the fields that belong to the table (it also filters out the id field, which the db will auto-generate).

Delete() and Deleteall() in Hibernate

Consider the below two methods to delete a Set of Employees with the name "John" .
List<Employee> list = new ArrayList<Employee>();
String query= " from Employee emp where emp.name = 'John'";
list=getHibernateTemplate().find(query);
First Method:
getHibernateTemplate().deleteAll(list);
Second Method:
Iterator<BulkChangeRequest> itList = list.iterator();
while(itList.hasNext()) {
Employee emp = itList.next();
getHibernateTemplate().delete(emp);
}
Do they differ significantly in terms of performance? Are both of them essentially the same i.e. does the deleteAll method delete row one by one?
Also wouldn't it be better to do it in SQL using the following query?
" delete from Employee where name = 'John'"
Yes. It would be better to use SQL or HQL to delete all employee records named 'John' rather then the first option. Simply because in first option, you have to load all employee record from db to delete. That's obviously an extra task.
I think, for delete() and deleteAll(), there will be no difference except in delete(), it will create new session for every call; whereas in deleteAll(), all objects will be deleted in one session. But the number of queries will be the same.
I suggest you read this section, one shot delete:
https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/performance.html#performance-collections-oneshotdelete
Deleting collection elements one by one can sometimes be extremely
inefficient. Hibernate knows not to do that in the case of an
newly-empty collection (if you called list.clear(), for example). In
this case, Hibernate will issue a single DELETE.

Kohana 3 ORM: Getting most repeated values, ranked, and inserting into new object / array

So, another in my series of Kohana 3 ORM questions :)
I have, essentially, a pivot table, called connections. The connections table connects a song to a keyword. That's all great and working (thanks to my last two questions!)
I want to output the most connected songs by keyword. So, to somehow query my connections table and output an object (with an arbitrarily limited number of iterations $n) that ranks songs by the number of times they have been connected, ie. the number of times that particular song_id appears for that particular keyword_id.
I have literally no idea how to achieve this, without querying every single row (!!!) and then counting those individual results in an array.... There must be a more elegant way to achieve this?
I believe this is more of an SQL question. Using the DB query builder:
DB::select('songs.*')->select(array('COUNT("keywords.id")', 'nconnections'))
->from('songs')
->join('connections', 'LEFT')->on('connections.song_id', '=', 'songs.id')
->join('keywords', 'LEFT')->on('connections.keyword_id', '=', 'keywords.id')
->group_by('songs.id')
->order_by('nconnections')
->as_object('Model_Song')
->execute();
or in SQL
SELECT `songs`.*, COUNT(`keywords`.`id`) AS `nconnections` FROM songs
LEFT JOIN `connections` ON `connections`.`song_id` = `songs`.`id`
LEFT JOIN `keywords` ON `connections`.`keyword_id` = `keywords`.`id`
GROUP BY `songs`.`id` ORDER BY `nconnections`
should return the result you want.
You'll want to have an accessible property called nconnections in your song model. The simplest way to do that is to add a public member so you don't tamper with ORM's inner workings.
I'm assuming you're using a model called 'Song', linked to a 'songs' table, a 'Keyword' model linked to a 'keywords' table and in the 'connections' table foreign keys 'song_id' and 'keyword_id' for each model respectively.

Table not getting updated while using LinQ

I am trying to update a table using LinQ. Though records are getting inserted, for some reason they are not getting updated.
what can be possible problem
Dim db as new empDataContext
Dim emptable as new employee
if update then
emptable=GetEmp(txtempID.Text)
emptable.Name="Test"
emptable.Age=11
emptable.City="NYC"
else
emptable.Name="Test"
emptable.Age=11
emptable.City="NYC"
emtable.deptID=10
db.employee.InsertOnSubmit(emptable)
end if
db.SubmitChanges()
Judging just from what I can see here, I'm guessing your GetEmp method is using a different data context to retreive the data than the one you're using to save it back to the DB.
When using LINQ to SQL, the context is what tracks the changes to the tables. If you're not careful and mix Contexts by accident, you can get strange behaviors like this.
You can test by chaging:
emptable=GetEmp(txtempID.Text)
to
// Returns the first matching employee with the id
emptable = (from e in db.Employees
where e.id == txtempid.Text).FirstOrDefault()
If you find that the context is the issue, just modify your GetEmp method to accept the context as a parameter rather than creating a new one itself.
What does GetEmp do? In particular, as presented it appears that it does not have a reference to the empDataContext named db. DataContexts are examples of identity maps and as such they track items that have been loaded from a persistence mechanism. If you are using a different DataContext in GetEmp then the DataContext db does not know about the instance of employee with SomeID equal to the value represented by txtempID.Text.
So either pass a reference to db into GetEmp or change your code to the following:
emptable = db.Single(Function(e as employee) e.SomeID=Int32.Parse(txtempID.Text))
then your update should work.
If I had to guess, I would say that the GetEmp() call is not using the same database context object. Therefore, Linq-To-SQL doesn't think any changes are occuring in the "db" database context.
Randy