Map to non managed entity with criteria-api - jpa-2.0

In JPA1 you could map a result to a non-managed entity by something like this:
Query query = entityManager.createQuery("SELECT NEW com.test.TestInfo(e.name, e.city) from Example e");
In JPA2 you could do it like this :
Query query = entityManager.createQuery(“SELECT e.name, e.city from Example e”,TestInfo.Class);
How would I do that with the criteria-api? I simply don't know the buzzwords to google for.
Any hints?
Jonny

That can be done via CriteriaBuilder.construct. First argument is class of result, following arguments are Selections.

Related

How to get and update Django object in one query?

To optimize a lot my database I would like to make as less as possible any query.
I'm trying to get an object, increment the field "count_limit" and make an If statement after on the Customer instance.
To achieve it I've made this query who worked well.
Customer.objects.filter(user=user).update(count_limit=F('count_limit') + 1)
So after this query, count_limit has been incremented by 1 as I wanted.
When I'm trying to get the Customer instance as a result of this query, it returns "1".
Is it possible to make both, update the instance and get it as a return object ?
Thanks a lot
The update() method will return the number of updated rows. If you are using Postgres, then you can use the returning clause with the raw query.
query = 'UPDATE customer SET count_limit=(customer.count_limit + 1) WHERE customer.user_id=%s returning *'
updated_obj = Customer.objects.raw(query, [user.id])
I don't know if this can be achieved by ORM, but suggestions will be appreciated.
Make sure that the table name in raw query is correct. If you haven't definer db_table in the meta class of your model, then by default it will be myapp_model.
And to prevent SQL injection, from the Docs:
Do not use string formatting on raw queries or quote placeholders in
your SQL strings!
Follow Docs on raw()
You are looking for F functions: https://docs.djangoproject.com/en/3.0/ref/models/expressions/#f-expressions
Example from their documentation how to increase a counter
from django.db.models import F
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

Django advanced LIKE filtering

So I'm trying to find a nice way to execute an advanced filter using the LIKE statement in Django.
Let's say I have the following records in a table called elements:
id = 1, name = 'group[1].car[8]'
id = 2, name = 'group[1].car[9]'
id = 3, name = 'group[1].truck[1]'
id = 4, name = 'group[1].car[10]'
id = 4, name = 'group[1].carVendor[1]'
I would like to select all elements that look like group[x].car[y].
To query this in SQL I would do:
SELECT * FROM elements WHERE name LIKE 'group[%].car[%]'
Now, by reading the Django documentation here, I see that the only pre-built LIKE statements are the following:
contains: name LIKE '%something%'
startswith: name LIKE 'something%'
endswith: name LIKE '%something'
So the one I need is missing:
plain like: name LIKE 'group[%].car[%]'
I'm also using Django Rest Framework to write up my API endpoints and also here we find the possibility to use:
contains: name__contains = something
startswith: name__startswith = something
endswith: name__endswith = something
So also here, the one I need is missing:
plain like: name__like 'group[%].car[%]'
Of course I know I can write a raw sql query through Django using the raw() method, but I would like to use this option if no better solution comes up, because:
I need to make sure my customization is safe
I need to extends the customization to DRF
Can anybody think of a way to help me out with this in a way to go with the flow with both Django and Django Rest Framework?
You can use a regular expression (regex) [wiki] for this, with the __iregex lookup [Django-doc]:
Elements.objects.filter(name__iregex=r'^group\[.*\].car\[.*\]$')
if between the square brackets, only digits are allowed, we can make it more specific with:
# only digits between the square brackets
Elements.objects.filter(name__iregex=r'^group\[\d*\].car\[\d*\]$')
Since some the specifications are a bit "complex" it is better to first test your regex, for example with regex101 you can look what names will be matched, and which will not.

Predicate query nested fetch

I have list of predicates and use them as below.
criteriaQuery = criteriaQuery.where(builder.and(toArray(predicates, Predicate.class)));
I use the fetch for lazy as below for Person entity.
Root<Employment> root = criteriaQuery.from(type);
root.fetch(Employment_.person);
However, I need to access education entity which is mapped in Person.
I tried as below but it doesn't work.
root.fetch(Employment_.person, Person_.education);
In other words I need to do a nested fetch somehow, any suggestions?
Because at the moment if I tried to access getEmployment().getPerson().getEducation() it goes to lazy exception

How To Utilize Doctrine2 Type Conversion on Native Query COLUMNS

Could not find anything on this-- seems like it should be straight forward though.
So the example the Doctrine2 docs give for type conversion on bound parameters looks like this:
$date = new \DateTime("2011-03-05 14:00:21");
$stmt = $conn->prepare("SELECT * FROM articles WHERE publish_date > ?");
$stmt->bindValue(1, $date, "datetime");
$stmt->execute();
What I want to do is specify the type conversion for one of the columns, but there is nothing in the documents or on StackOverflow that I could find. A pseudo-example of what this might look like:
$stmt = $conn -> prepare("SELECT datetime FROM articles WHERE id = 1");
$stmt -> setType(0, "date_type"); // 0 being the column position, "date_type" being the PHP type to convert to
If anybody knows how to do this, (this is SQL not DQL), I would greatly appreciate. Thank you.
This is not something that works at DBAL level. If you are using NativeSQL Queries in ORM, you can get that kind of conversion through hydration (see the NativeSQL section in the Doctrine ORM documentation) by using the HYDRATE_ARRAY mode and mapping some of the fetched fields to an entity. The fastest solution (if you don't intend to use ORM) is to iterate over the results and applying the type conversion manually by accessing Doctrine\DBAL\Types\Type::getType($someType)->convertToPhpValue($fetchedValue). It could be a valuable addition to ORM to be able to specify a third parameter stating the fetched type in Doctrine\ORM\Query\ResultSetMapping#addScalarResult.

converting linq query to icollection

I need to take the results of a query:
var query = from m in db.SoilSamplingSubJobs where m.order_id == id select m;
and prepare as an ICollection so that I can have something like
ICollection<SoilSamplingSubJob> subjobs
at the moment I create a list, which isnt appropriate to my needs:
query.ToList();
what do I do - is it query.ToIcollection() ?
List is an ICollection. You can change you query.ToList() code to the following.
query.ToList() as ICollection<SoilSamplingSubJob>;
You question sounds like this query is returned as a function result. If this is the case remember that the Linq to SQL objects are connected by default so you will need to manage where your database context get opened and closed. Alternatively you can create DTOs (Data Transfer Objects) that hold the data you want to use in the rest of your program. These objects can fit into your object hierarchy any way you want.
You can also create these DTOs as part of the query.
var query = from m in db.SoilSamplingSubJobs where m.order_id == id
select new SubJobDTO {
OrderNumber = m.order_id
};
return query.ToList() as ICollection<SubJobDTO>;
Since, query implements IEnumerable, you can pass it to the constructor of the collection of your choice. ICollection is an interface, implemented by several classes (including List<T>, which ToList returns) with different performance characteristics.
With slightly different syntax, you can do something like this as well that can cut down on what goes into the ICollection. This type of approach is great for Angular and MVC when you have a huge table but only want to load some props into the cshtml page:
ICollection<SoilSamplingSubJob> samples = dbContext.GetQuery().Where(m => m.order_id == id)
.AsEnumerable().Select(s => new
{
Id = s.order_id,
CustomProperty = s.some_thing
}).ToList() as ICollection<SoilSamplingSubJob>