SELECT FOR UPDATE in Doctrine 2 DQL - doctrine-orm

I use pessimistic locking quite a lot in my application, and it works fine when using the Entity Manager:
$em->find($class, $id, LockMode::PESSIMISTIC_WRITE);
This results in a SELECT FOR UPDATE when using MySQL.
Now I need to use the same locking but for entities retrieved with a DQL query.
Is it possible to use pessimistic locking in DQL?

Found the solution, using Query::setLockMode():
$query = $this->em->createQuery('SELECT ...');
$query->setLockMode(LockMode::PESSIMISTIC_WRITE);

Related

Use DynamoDBVersionAttribute when creating a new DynamoDB Table in Java

I'm trying to add a DynamoDBVersionAttribute to incorporate optimistic locking when accessing/updating items in a DynamoDB table. However, I'm unable to figure out how exactly to add the version attribute.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html seems to state that using it as an annotation in the class that creates the table is the way to go. However, our codebase is creating new tables in a format similar to this:
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);
List<AttributeDefinition> attributeDefinitions= new
ArrayList<AttributeDefinition>();
attributeDefinitions.add(new
AttributeDefinition().withAttributeName("Id").withAttributeType("N"));
List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new
KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH));
CreateTableRequest request = new CreateTableRequest()
.withTableName(tableName)
.withKeySchema(keySchema)
.withAttributeDefinitions(attributeDefinitions)
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits(5L)
.withWriteCapacityUnits(6L));
Table table = dynamoDB.createTable(request);
I'm not able to find out how to add the VersionAttribute through the Java code as described above. It's not an attribute definitions so unsure where it goes. Any guidance as to where I can add this VersionAttribute in the CreateTable request?
As far as I'm aware, the #DynamoDBVersionAttribute annotation for optimistic locking is only available for tables modeled specifically for DynamoDBMapper queries. Using DynamoDBMapper is not a terrible approach, since it effectively creates an ORM for CRUD operations on DynamoDB items.
But if your existing codebase can't make use of it, your next best bet is probably to use conditional writes to increment a version number if it's equal to what you expect it to be (i.e. roll your own optimistic locking). Unfortunately, you would need to include the increment / condition to every write you want to be optimistically locked.
Your code just creates a table, but then in order to use DynamoDBMapper to access that table, you need to create a class that represents it. For example if your table is called Users, you should create a class called Users, and use annotations to link it to the table.
You can keep your table creation code, but you need to create the DynamoDBMapper class. You can then do all of your loading, saving and querying using the DynamoDBMapper class.
When you have created the class, just give it a field called version and put the annotation on it, DynamoDBMapper will take care of the rest.

Doctrine ORM how to save an UPDATE of my object to the database (equivalent of SQL UPDATE query)

I'm new to Doctrine and I can't seem to find an answer to this.
To save a newly created object to the database (equivalent of SQL INSERT query), I'm using
$this->getEntityManager()->persist($category);
$this->getEntityManager()->flush($category);
And to delete one (equivalent of SQL DELETE query), I'm using
$this->getEntityManager()->remove($category);
$this->getEntityManager()->flush($category);
Now, how do I save updates to my $category object to the database? I'm looking for the Doctrine equivalent of an UPDATE query.
Surely Doctrine ORM must have a simple method to do this, without having to use DQL?
Well there is no need for specific update query.
With doctrine you can update objects like this. Let's suppose you have category object with field name. So we will try to update it.
$newName = 'hello world';
$category->setName($newName);
$this->em->flush(); // without passing the object
This will update you entity.
So following up from this, we have learnt, that you can update entities, by just using setters and setting new values, and after that you flush. It will handle things automatically.

Using C++ SQL to Add Relationship to Microsoft Access Table

I'm trying to add a CONSTRAINT/RELATIONSHIP between two Microsoft Access Tables using C++ (MFC-based) (through ODBC) with the following SQL Command:
ALTER TABLE [JobSettingsReporting]
ADD CONSTRAINT FK_PerEntry
FOREIGN KEY (JobSetID)
REFERENCES JobSettingsEntry(JobSetID)
ON UPDATE CASCADE
ON DELETE CASCADE
I tried to do it with this:
CDatabase db;
db.OpenEx(App().GetDBConnectString());
db.ExecuteSQL(strSQL);
db.Close();
where strSQL is the Query above. I'm getting the error:
Syntax error in CONSTRAINT clause.
It seems the problem is with the "ON UPDATE CASCADE" and "ON DELETE CASCADE" components. I get the same error when I use the Query Design tool (or in VB) within Microsoft Access.
However, when I do the following in VB in Microsoft Access, it works:
Dim cn As ADODB.Connection 'For action queries
Set cn = CurrentProject.Connection
cn.Execute "ALTER TABLE [JobSettingsReporting]
ADD CONSTRAINT FK_PerEntry
FOREIGN KEY (JobSetID)
REFERENCES JobSettingsEntry(JobSetID)
ON UPDATE CASCADE
ON DELETE CASCADE"
This command also seems to work in SQL Server Express when directly using the Query Window.
It is my understanding that I need to use Jet/ADO to issue this command in C++ for it to work but I'm having trouble finding the syntax. I need to add this relationship programmatically so that it will update the databases on all the deployed machines.
Any help would be appreciated.

Django does a useless join when filtering

I have an optional foreign key for a parameter:
class Club(models.Model):
...
locationid = models.ForeignKey(location_models.Location, null=True)
...
I want to find entries of club where this foreignkey is not set. Here's the ORM query:
print Club.objects.filter(locationid=None).only('name').query
Produces
SELECT `club_club`.`id`, `club_club`.`name` FROM `club_club`
LEFT OUTER JOIN `location_location`
ON (`club_club`.`locationid_id` = `location_location`.`id`)
WHERE `location_location`.`id` IS NULL
Same query is produced when I do filter(locationid_id__isnull=True)
What I want is to query on locationid_id without involving a JOIN. I know I can write raw SQL, but is there an ORM-al way of doing this?
This seems to be quite a persistent issue, and the patch that fixed it had other side effects, so it never got applied to a release version of Django.
A solution to this is to use the extra method. This will require raw SQL, but only a limited amount and using SQL standards, so it should be compatible with all SQL databases:
location_null = '`%s`.`%s` IS NULL' % (Club._meta.db_table, Club.locationid.field.column)
Club.objects.extra(where=[location_null])
You can add this as a manager/queryset method for a more DRY solution.
The other option is to just take the performance hit. This is what I would recommend, unless benchmarking shows that the performance hit really is unacceptable in your specific case.

doctrine: QueryBuilder vs createQuery?

In Doctrine you can create DQL in 2 ways:
EntityManager::createQuery:
$query = $em->createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1');
QueryBuilder:
$qb->add('select', 'u')
->add('from', 'User u')
->add('where', 'u.id = ?1')
->add('orderBy', 'u.name ASC');
I wonder what the difference is and which should I use?
DQL is easier to read as it is very similar to SQL. If you don't need to change the query depending on a set of parameters this is probably the best choice.
Query Builder is an api to construct queries, so it's easier if you need to build a query dynamically like iterating over a set of parameters or filters. You don't need to do any string operations to build your query like join, split or whatever.
Query builder is just, lets say, interface to create query... It should be more comfortable to use, it does not have just add() method, but also methods like where(), andWhere(), from(), etc. But in the end, it just composes query like the one you use in the createQuery() method.
Example of more advanced use of query builder:
$em->createQueryBuilder()
->from('Project\Entities\Item', 'i')
->select("i, e")
->join("i.entity", 'e')
->where("i.lang = :lang AND e.album = :album")
->setParameter('lang', $lang)
->setParameter('album', $album);
They have different purposes:
DQL is easier to use when you know your full query.
Query builder is smarter when you have to build your query based on some conditions, loops etc.
The main difference is the overhead of calling the methods. Your first code sample (createQuery) just for simplicity makes one method call, while the the queryBuilder makes 4. At the end of everything, they come down to a string that has to be executed, first example you are giving it the string, and the other you are building it with multiple chained method calls.
If you are looking for a reason to use one over the other, that is a question of style, and what looks more readable. For me, I like the queryBuider most of the time, it provides well defined sections for the query. Also, in the past it makes it easier to add in conditional logic when you need it.
It might be easier to unit test when using the query builder. Let's say you have a repository that queries for some data basing on the complicated list of conditions. And you want to assure that if a particular condition is passed into the repository, some other conditions are added into the query. In case of DQL you have two options:
1) To use fixtures and test the real interaction with DB. Which I find somewhat troublesome and ununitestish.
2) To check the generated DQL code. Which can make your test too fragile.
With QueryBuilder, you can substitute it with mock and verify that "andWhere" method with needed parameter is called. Of course such considerations are not applicable if your query is simple and not depended on any parameters.