Chaining queries in Play! Framework - activerecord

is there a way to chain queries in the "Play!" framework instead of manually writing a query ?
Something like:
Model m = Model.where("name","Bill").where("gender","m").first();
I wonder because I recently switched from Codeigniter + dmz to grails then now to "Play!" and have been a bit disappointed by the queries chaining compared to the framework mentioned above
PS: I'm obviously not talking about the fetch() and the from() methods.

There is a JpqlSelect object with wich you can do
public static Model findBill() {
JpqlSelect select = new JpqlSelect().from("Model").where("name=?").param("Bill").andWhere("gender=?").param("m");
return find(select.toString(), select.getParams().toArray()).first();
}
This helper is far from being complete but it may suits your needs

You can do it with java.persistence Criteria API like that:
CriteriaQuery q = JPA.em().getCriteriaBuilder().createQuery(Model.class)
q.where(<Expression>).where(<Expression>);
TypedQuery<Model> tq = JPA.em().createQuery(q);
List<Model> result = tq.getResultList();
Look here and here for start

An other option could be using http://www.querydsl.com/ with it's jpa integration.

Related

MongoTemplate, Criteria and Hashmap

Good Morning.
I'm starting to learn some mongo right now.
I'm facing this problem right now, and i'm start to think if this is the best approach to resolve this "task", or if is bettert to turn around and write another way to solve this "problem".
My goal is to iterate a simple map of values (key) and vector\array (values)
My test map will be recived by a rest layer.
{
"1":["1","2","3"]
}
now after some logic, i need to use the Dao in order to look into db.
The Key will be "realm", the value inside vector are "castle".
Every Realm have some castle and every castle have some "rules".
I need to find every rules for each avaible combination of realm-castle.
AccessLevel is a pojo labeled by #Document annotation and it will have various params, such as castle and realm (both simple int)
So the idea will be to iterate a map and write a long query for every combination of key-value.
public AccessLevel searchAccessLevel(Map<String,Integer[]> request){
Query q = new Query();
Criteria c = new Criteria();
request.forEach((k,v)-> {
for (int i: Arrays.asList(v)
) {
q.addCriteria(c.andOperator(
Criteria.where("realm").is(k),
Criteria.where("castle").is(v))
);
}
});
List<AccessLevel> response=db.find(q,AccessLevel.class);
for (AccessLevel x: response
) {
System.out.println(x.toString());
}
As you can see i'm facing an error concerning $and.
Due to limitations of the org.bson.Document, you can't add a second '$and' expression specified as [...]
it seems mongo can't handle various $and, something i'm pretty used to abuse over sql
select * from a where id =1 and id=2 and id=3 and id=4
(not the best, sincei can use IN(), but sql allow me)
So, the point is: mongo can actualy work in this way and i need to dig more into the problem, or i need to do another approach, like using criterion.in(), and make N interrogation via mongotemplate one for every key in my Map?

Getting first row from a resultset with sort by descending using QueryDsl predicate and spring jpa

I am new to spring JPA . I have one query such that i've to get the resultset and take only the row at the top.I dont know how to do it in spring JPA.And i dont want it to be done using #Query annotation,Since i was asked not to go with any queries inside the code.This is the uery i want to convert
My Query
SELECT id,name FROM example_table ORDER BY id DESC LIMIT 1;
I tried something like this in my predicate file:
public Predicate getLatest(){
QExampleTable example = QExampleTable.exampleTable;
return (Predicate) example.id.desc();
}
and this is how my jpa repository looks like:
public ExampleTable findOne(MyPredicate.getLatest());
But this is'nt working out and i know it wont clearly.But I seriously dont know how to convert this above query.Can anyone help me out with this
You can do it using just QueryDSL without Predicate and Repositories.
List<ExampleTable> examples = new JPAQuery()
.from(QExampleTable.exampleTable)
.limit(1)
.orderBy(new OrderSpecifier<>(Order.DESC, QExampleTable.exampleTable.id))
.list(QExampleTable.exampleTable);
you can use offset or limit functions.
In your case .limit(1) should be enough
This won't work because desc() returns an OrderSpecifier that must be used with Query.orderBy().
The following could work, though it's not a "pure" Predicate:
public Predicate getLatest() {
QExampleTable example = QExampleTable.exampleTable;
return example.id.eq(new JPASubQuery().from(example).unique(example.id.max()));
}
I'm afraid a more clean solution is that you provide a CustomRepository + implementation.
With QueryDSL for me, the option that is working is using max().
JPAExpressions.selectFrom(QExampleTable.exampleTable)
.select(QExampleTable.exampleTable.max())

Entity Framework slow with optional where clauses

Below is a snippit of simplified version of a problem I am having with Entity Framework v4 where the first load seems to take around 30 seconds on a table with 36 rows!
After that it is very quick to load until you change the search params, then it takes 30 seconds again but once that combination of search params has been done once it is quick.
This is repeated each time a different combination of params is used.
IQueryable<User> result= GetAllUsers();
if (!String.IsNullOrWhiteSpace(firstNameSearchParam))
{
result = result.Where(u => u.firstname.contains(firstNameSearchParam))
}
if (!String.IsNullOrWhiteSpace(lastNameSearchParam))
{
result = result.Where(u => u.lastname.contains(lastNameSearchParam))
}
Var ret = result.ToArray();
Any ideas would be really appreciated.
I'm not sure if pre-compiling the views will help. I tried but couldn't get it to work.
how long it takes when you execute the query from the sql side?
you can use this idea mentioned by scott here on this link Dynamic Linq
and i think this will work with you also with Entity Framework, and there is another idea that you can use the entity framework metadata
hope that this will help you
regards

Entity Framework LINQ Query using Custom C# Class Method - Once yes, once no - because executing on the client or in SQL?

I have two Entity Framework 4 Linq queries I wrote that make use of a custom class method, one works and one does not:
The custom method is:
public static DateTime GetLastReadToDate(string fbaUsername, Discussion discussion)
{
return (discussion.DiscussionUserReads.Where(dur => dur.User.aspnet_User.UserName == fbaUsername).FirstOrDefault() ?? new DiscussionUserRead { ReadToDate = DateTime.Now.AddYears(-99) }).ReadToDate;
}
The linq query that works calls a from after a from, the equivalent of SelectMany():
from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
from d in g.Discussions
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count()
};
The query that does not work is more like a regular select:
from d in oc.Discussions
where d.Group.Name == "Student"
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count(),
};
The error I get is:
LINQ to Entities does not recognize the method 'System.DateTime GetLastReadToDate(System.String, Discussion)' method, and this method cannot be translated into a store expression.
My question is, why am I able to use my custom GetLastReadToDate() method in the first query and not the second? I suppose this has something to do with what gets executed on the db server and what gets executed on the client? These queries seem to use the GetLastReadToDate() method so similarly though, I'm wondering why would work for the first and not the second, and most importantly if there's a way to factor common query syntax like what's in the GetLastReadToDate() method into a separate location to be reused in several different other LINQ queries.
Please note all these queries are sharing the same object context.
I think your better of using a Model Defined Function here.
Define a scalar function in your database which returns a DateTime, pass through whatever you need, map it on your model, then use it in your LINQ query:
from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
from d in g.Discussions
select new
{
UnReadPostCount = d.Posts.Where(p => p.CreatedDate > myFunkyModelFunction(fbaUsername, p.Discussion)).Count()
};
and most importantly if there's a way to factor common query syntax like what's in the GetLastReadToDate() method into a separate location to be reused in several different places LINQ queries.
A stored procedure would probably be one way to store that 'common query syntax"...EF, at least 4.0, works very nicely with SP's.

How to create a dynamic linq query for filter based on ria service?

Suppose I have a table Person(PersonID, Name, ....). Then I use EF to create a Entity model and then create DomainService based on Ria Service. At client side(sliverlight), I try to create a dynamic linq for filter function. What I did is:
q = EntityQuery<MyData.Person>
q = q.Where(p=> p.Name.Contains(NameVar));
That is fine. Then I have another two tables for phone:
Phone(PhoneID, PhoneNumber, ...)
PersonPhone(PersonID, PhoneID, ...)
Then I want to add filter to match PhoneNumber. How to write the linq query q like?
q = q.Where(p => p.PersonPhone.
Where(ph=>ph.PhoneNumber.Contains(PhoneVar)&& ph.PersonID == p.PersonID).Count()>0);
I can pass the compiliation, but when run the app, I got error:
Query operator 'Count' is not supported
How to resolve this problem?
This sounds like a good scenario for writing a custom query method on the server and invoking that method instead of the default query for Person. RIA Services only supports a subset of LINQ operations on the client, but you can use all LINQ operators on the server.
You need to use the QueryBuilder
Here's a sample
var qb = new QueryBuilder<Person>().Where(p => p.PersonPhone.Where(ph=>ph.PhoneNumber.Contains(PhoneVar)&& ph.PersonID == p.PersonID).Count()>0);
Then you can take qb and apply it to whatever query you like.
query = qb.ApplyTo(query);
By using Func<QueryBuilder<Person>> you can pass around your dynamic filter into common controls and etc. And when you invoke the function you'll get the current values from that ViewModel.

Resources