Say I have a repository of cats with weight property, if I wanted to find the heaviest cat I have to do this:
Page<Cat> cats = catRepository.findAll(new PageRequest(0, 1, Sort.Direction.DESC), "weight");
Iterator<Cat> it = cats.iterator();
if(cats.hasNext()) {
Cat heaviest = it.next();
} else {
}
Trying to simply put Cat findOneOrderByWeightDesc() on the repository interface isn't supported.
Is there any simpler way to achieve this on spring data jpa?
Edit 5 July 2014: Thomas Darimont has kindly implemented a new feature that solves the problem above: http://jira.spring.io/browse/DATACMNS-516
List<Cat> findAllByOrderByWeightDesc();
should work fine.
In that case you could use a native query:
This should work with every database:
#Query(value = "select a.* from #{#entityName} a LEFT JOIN #{#entityName} b ON a.id = b.id AND a.weight < b.weight WHERE b.id IS NULL", nativeQuery = true)
Iterable<Cat> findHeaviestCat1();
Here is an mysql specific variant:
#Query(value = "select a.* from #{#entityName} a LEFT JOIN #{#entityName} b ON a.id = b.id AND a.weight < b.weight WHERE b.id IS NULL limit 1", nativeQuery = true)
Cat findHeaviestCat2();
Related
//I have a sql like this
SELECT
x.attr1,
p.attr2,
p2.attr3,
o.attr4,
p2.attr5,
a2.attr6
FROM TABLE_O o
RIGHT JOIN TABLE_A a ON a.id = o.id AND a.id2 IS NULL
LEFT JOIN TABLE_A a2 ON a2.id = o.id AND a2.id2 = a.id3
LEFT JOIN TABLE_P p ON a.id4 = p.id4
LEFT JOIN TABLE_P p2 ON a2.id4 = p2.id4
INNER JOIN TABLE_X x ON a.id3 = x.id3
WHERE o.type = 'someText' AND a2.id4
IN ( SELECT id3 FROM TABLE_P WHERE TYPE = "anotherText")
AND x.attr1 = "someText"
//I need an idea about how can i do this on mongo aggregates, thanks.
nosql is a non-relational database type. but The following link may be useful.
mongodb aggregation
Hi is it possible to translate the below queries into linq ? ...
I am using entity frameworks core and tried to use the stored procedure but it seems like i have to create a model that applies to the metadata of the stored procedure. So i am trying to understand whether this kinda such query can be translated into linq so i don't have to create a separate db model.
SELECT
Stock.stockID ProductID,
stockName ProductName,
categoryName ProductCategory,
typeName ProductType,
sizeName ProductSize,
currentQuantity CurrentQuantity,
standardQuantity QuantityPerBox,
CONVERT(VARCHAR(255),CONVERT(INT,Stock.price)) AvgUnitCost,
CONVERT(VARCHAR(255),CONVERT(INT,x.lastUnitCost)) LastOrderUnitCost,
CONVERT(VARCHAR(10),CONVERT(DATE,x.lastOrderDate)) LastOrderDate
FROM dbo.Stock
LEFT JOIN
(
SELECT stockID,unitPrice lastUnitCost ,orderDate lastOrderDate, ROW_NUMBER() OVER (PARTITION BY stockID ORDER BY orderDate DESC) rn FROM dbo.SalesOrder
JOIN dbo.SalesOrderDetail ON SalesOrderDetail.salesOrderID = SalesOrder.salesOrderID
WHERE customerID = #customerID AND salesStatus = 'S'
) x ON x.stockID = Stock.stockID AND rn = 1
LEFT JOIN dbo.StockCategory ON StockCategory.stockCategoryID = Stock.stockCategoryID
LEFT JOIN dbo.StockType ON StockType.stockTypeID = Stock.stockTypeID
LEFT JOIN dbo.StockSize ON StockSize.stockSizeID = Stock.stockSizeID
WHERE disStock = 0
Almost everything is possible. you just need to be careful with performance.
var query =
from stock in db.Stocks
join x in (
from grp in (
from so in db.SalesOrders
join sod in db.SalesOrderDetails on so.SalesOrderId equals sod.SalesOrderId
where so.CustomerId == customerId && so.SalesStatus == "S"
orderby so.OrderDate descending
select new {
sod.StockId,
LastUnitCost = sod.UnitPrice,
LastOrderDate = so.OrderDate
} into inner
group inner by inner.StockId)
select grp.Take(1)) on x.StockId equals stock.StockId into lastStockSales
from x in lastStockSales.DefaultIfEmpty()
join sc in db.StockCategories on stock.StockCatergotyId equals sc.StockCategoryId into scLeft
from sc in scLeft.DefaultIfEmpty()
join st in db.StockTypes on stock.StockTypeId equals st.StockTypeId into stLeft
from st in stLeft.DefaultIfEmpty()
join ss in db.StockSizes on stock.StockSizeId equals ss.StockSizeId into ssLeft
from ss in ssLeft.DefaultIfEmpty()
where stock.DisStock == 0
select new MyDTO {
ProductId = stock.StockId,
ProductName = stock.StockName,
ProductType = st.TypeName,
ProductSize = ss.SizeName,
CurrentQuantity = stock.CurrentQuantity,
QuantityPerBox = stock.StandardQuantity,
AvgUnitCost = stock.Price,
LastOrderUnitCost = x.LastUnitCost,
LastOrderDate = x.LastOrderDate
};
As you can see is easy to rewrite these queries, I had to change a little bit the logic on how to get the latest sales for a stock item since ROW_NUMBER() OVER (PARTITION... is not supported from a LINQ perspective. Again, you would have to consider performance when rewriting queries.
Hope this helps.
I have been searching for a while, I haven't found any responses to my problem.
I am making an application in JSF, EclipseLink, Glassfish in which the user can have one or more groups. The application contains modules and permissions as follows:
Module => permission => utilisateur
Module => permission => groupe => utilisateur
I am looking for a criteria query (not in jqpl) to get all of the modules of a user. I have constructed my SQL query, which functions very well like this:
SELECT *
FROM core_module m
WHERE m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON mp.modules_id = m.id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN users_permissions up
ON p.id = up.permissions_id
INNER JOIN core_user u
ON u.id = 1
)
OR m.id IN (
SELECT m.id
FROM core_module m
INNER JOIN modules_permissions mp
ON m.id = mp.modules_id
INNER JOIN core_permission p
ON p.id = mp.permissions_id
INNER JOIN groups_permissions gp
ON gp.permissions_id = p.id
INNER JOIN core_group g
ON g.id = gp.groups_id
INNER JOIN users_groups ug
ON g.id = ug.groups_id
INNER JOIN core_user u
ON u.id = ug.users_id
WHERE u.id = 1
)
I am trying somehow to transform this into a criteria query without great success. I have just started the first part of the query, which gives me the modules immediately accessible to a user. I have the impression that I am missing some conditions or joins, as I am getting 2 results when I shouldn't be getting any. In effect, I haven't been able to include my ON clauses, so I can't change my to joins in my query since the entities don't exist: the table modules_permissions is created by a #ManyToMany in my entities...
Here is my first draft subquery:
List<Module> modules;
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Root<User> root_user = query.from(User.class);
Root<Permission> root_permission = query.from(Permission.class);
Root<Group> root_group = query.from(Group.class);
Join<Module, Permission> join_module_permission = root_module.join(Module_.permissions);
Join<Permission, User> join_permission_user = root_permission.join(Permission_.users);
query.where(cb.equal(root_user.get(User_.email), current.getEmail()));
modules = getEntityManager().createQuery(query).getResultList();
Try turning EclipseLink logging to finest so you can see the SQL that is generated. You might also use JPQL as it is closer to the SQL, and then convert to criteria once you have something working. Something like
"select m from Module m where
m in (select m1 from Module m1 join m1.permissions p join p.users u where u.id = 1) or
m in (select m2 from Module m2 join m2.permissions p2 join p2.groups g join g.users u2 where u2.id =1)"
The key here is that you use the entity relationships in the criteria query so that it matches what you want in the generated SQL. Don't use multiple from clauses when you only want those tables and their joins included in an inner query. If the above JPQL works and the relationships exist, something like this is equivalent:
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = criteriaQuery.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.users);
subquery.where(criteriaBuilder.equals(user1.get(User_.id), 1));
Subquery<Integer> subquery2 = criteriaQuery.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.groups).join(Group_.users);
subquery2.where(criteriaBuilder.equals(user2.get(User_.id), 1));
query.where(criteriaBuilder.or(criteriaBuilder.in(path ).value(subquery),
criteriaBuilder.in(path ).value(subquery2)));
The final answer is :
in JPQL :
#NamedQuery(name = "core_user.findModuleAssociated", query = "select m from Module m where m.id in (select m1.id from Module m1 join m1.permissions p join p.user u where u.id = :userid) or m.id in (select m2.id from Module m2 join m2.permissions p2 join p2.group g join g.users u2 where u2.id = :userid)")
in criteria query :
List<Module> modules;
CriteriaQuery<Module> query = cb.createQuery(Module.class);
Root<Module> root_module = query.from(Module.class);
Path path = root_module.get(Module_.id);
Subquery<Integer> subquery = query.subquery(Integer.class);
Root subRoot = subquery.from(Module.class);
subquery.select(subRoot.get((Module_.id)));
Join user1 = subRoot.join(Module_.permissions).join(Permission_.user);
subquery.where(cb.equal(user1.get(User_.id), current.getId()));
Subquery<Integer> subquery2 = query.subquery(Integer.class);
Root subRoot2 = subquery.from(Module.class);
subquery2.select(subRoot2.get((Module_.id)));
Join user2 = subRoot2.join(Module_.permissions).join(Permission_.group).join(Group_.users);
subquery2.where(cb.equal(user2.get(User_.id), current.getId()));
query.where(cb.or(cb.in(path).value(subquery), cb.in(path).value(subquery2)));
modules = getEntityManager().createQuery(query).getResultList();
Special thanks to Chris
I am new to Entity framwork and currently trying hard to get used this programming paradigm. I have this query which i want to write in Entity SQL.
SELECT f.id, f.personName, c.Category, j.busCode, s.description, f.StartDate, (SELECT COUNT(*) FROM Analysis WHERE id = f.id) As numOfAnalysis
FROM forms f
INNER JOIN Jobs j ON f.id = j.id
INNER JOIN category c ON j.categoryid = c.categoryid
INNER JOIN stage s ON f.stageid = s.stageid
WHERE j.busCode NOT IN ('xyz', 'YYY')
ORDER BY startDate
I can get records from two tables but as soon as i add third table using the navigation property, i get error table category is not loaded in the current context. I am using .net 3.5. Keep in mind that EDM V2 doest not have foreign keys and i think the only way to traverse through the table relationship is navigation property.
Any help will be deeply appreciated.
Thanks
Coder74
If you use should be able to mount this Linq query.
I tried to put together, but in the rush and no such test is complicated.
You can use this reference as support: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
var result = (from f in forms
join j in Jobs on f.id equals j.id
join c in Category on j.categoryid equals c.categoryid
join s in stage on f.stageid equals s.stageid
join a in Analysis on a.id equals f.id
where !(new int[] { 'xyz', 'YYY' }).Contains(j.busCode)
orderby f.StartDate
select {
id =f.id,
personName = f.personName,
Category = c.Category,
busCode = j.busCode,
description = s.description,
StartDate = f.StartDate,
numOfAnalysis = a.Count()
}).ToList()
Julio Spader
W&S Soluções de Internet
Can anyone tell me how to write the following query in Entity Framework 4.0? "Blogs" and "Categories" are my entities. The query basically returns me the list of categories and the number of blogs that are in that category.
SELECT b.CategoryId, c.Value, Count(b.Id) AS [Count] FROM dbo.Blogs b
INNER JOIN dbo.Categories c ON b.CategoryId = c.Id
GROUP BY b.CategoryId, c.Value
Thanks in advance.
The following should work (LinqToEntities):
var categories = from c in oc.Categories
select new
{
CategoryId = c.Id,
c.Value,
Count = c.Blogs.Count()
}
This will give you a list of category ids and values and for each category id you get the number of blogs in that category.
EDIT: To give an answer to the question in your comment: this isn't possible in LinqToEntities but you can do it in Entity SQL.
var results = new ObjectQuery<DbDataRecord>(
#"SELECT y, COUNT(y)
FROM MyEntities.Blogs AS b
GROUP BY YEAR(b.CreatedDate) AS y", entities).ToList();
var nrBlogsPerYear = from r in results
select new { Year = r[0], NrBlogs = r[1] };
In the Entity SQL query, you should replace MyEntities with the name of your context.
EDIT: As I just found out through a comment by Craig, grouping by year is possible in L2E so you can write your query like this:
var nrBlogsPerYear = from b in oc.Blogs
group b by b.CreatedDate.Year into g
select new { Year = g.Key, NrBlogs = g.Count() };
If you have navigation properties in your entities, you can do that :
var cats = from c in db.Categories
let count = c.Blogs.Count()
where count > 0
select new
{
CategoryId = c.Id,
Value = c.Value,
Count = count
};
If you prefer to use an explicit join, you can do it like that :
var cats = from c in db.Categories
join b in db.Blogs on c.Id equals b.CategoryId into g
select new
{
CategoryId = c.Id,
Value = c.Value,
Count = g.Count()
};
var query = from p in B.Products
join c in B.Categories on p.CategoryID equals c.CategoryID
orderby c.CategoryName,p.ProductName
select new
{
c.CategoryName ,
p.ProductName,
p.ReorderLevel
};
GridView1.DataSource = query.ToList();
GridView1.DataBind();