Custom paging query cannot return Page<T> type? - spring-data-jdbc

official document#jdbc.query-methods
List<Person> findByFirstnameOrderByLastname(String firstname, Pageable pageable);
If you change the return type from List to Page, an error will occur. Is there any solution?
I can think of adding count() method, and then calling PageableExecutionUtils.getPage(...) to get the result. I don't want to write a count() method.

Page and Slice currently aren't supported as return types.
The workaround you hint at it the recommended way to do it currently: Return a list, have a separate count-query and combine the results into a Page using PageableExecutionUtils.getPage.
Anybody interested in this feature might want to watch DATAJDBC-554.

Related

Quarkus PanacheEntityBase query with IN

I have a customer entity of type PanacheEntityBase. I would like get all customers by ids
I can get it with customer.list("customerId", id) in a loop. I dont think its a good solution. I prefer using IN. Please suggest how to use IN with PanacheEntityBase
I solved the problem with customerEntity.list("customerId IN (?1)", customerIds);
Note: customersids must be a java list (Array did not work)

Laravel - trouble with Eloquent Collection methods such as last()

I have a variable $courses that in my debugger is shown as type App/Courses
In the model, there is a one to many relation and I retrieve these related items in the model and then access as $courses->relateditems
In the debugger, $courses->relateditems is shown as type Illuminate/Database/Eloquent/Collection
Ok, all makes sense.
I want to get last item in the $courses->relateditems collection. So I try
$courses->relateditems->last()->startdate
But this is not returning the value that I know exists. And when I evaluate the expression $courses->relateditems->last() in the debugger I get this in my laravel.log:
Symfony\Component\Debug\Exception\FatalErrorException: Cannot access self:: when no class scope is active in /app/Courses.php:68
I am just not sure what is going on. I know I can use DB queries to just get the data I need, but I have a model event triggering a function and that function receives the $courses object/model (or however we name it) and I am just trying to get this working as above.
Ideas on what I am doing wrong?
thanks,
Brian
The issue here based on the error you have at the bottom of your post is a mistake in your code.
However, I think you've misunderstood how Laravel relationships work. They essentially come in two forms on a model, that of a property and that of a method.
relateditems Is a magic property that will return the result of a simple select on the relationship if one has already been performed. If one hasn't been performed it will perform one and then return it, known as eager loading.
relateditems() Is a method that returns a query builder instance for that relationship.
By calling relateditems->last() you're loading ALL related items from the database and then getting the last, which is less than optimal.
The best thing for you to do is this:
$course->relateditems()->orderBy('id', 'desc')->first();
This will get the first item return, however, since we've ordered it by id in descending order, it'll be reversed from what could be considered its default ordering. Feel free to change the id to whatever you want.

Passing parameters to Liferay's services search function

I need to use Liferay's index for searching users that match a determined string, and this is possible by using UserLocalServiceImpl#search(long companyId, String keywords, int status, LinkedHashMap<String,Object> params, int start, int end, com.liferay.portal.kernel.search.Sort sort).
Furthermore I'd like to be able to filter the users by UserGroup.
I would expect that I could pass the userGroupId to this function into params, but it doesn't look like I can find any documentation about what params should be.
By taking a look at the source code it looks like it is being added to a SearchContext used to produce the query, but I'm not being able to follow down the code to the point where is then used.
Do anyone know anything about what can I put into params for this purpose?
I'm on a Liferay CE version 7.0
Please have a look add UserIndexer.java in method addContextQueryParams.
It looks like the param key should be usersGroups an it should hava a Long[] value. There are some other keys handled here, so you could gain some information how params are processed here (debugger?).

Why does Laravel Controller needs (integer) cast in Homestead, but not in production server

(integer) cast must be done in Homestead for Controller parameter
I am having a hard time searching for the cause of a discrepancy between my local dev environment (Homestead) and the hosted one.
I define a route like this:
Route::get('group/{id}/data', 'GroupDataController#index');
And the code in the Controller looks like this:
public function index($id)
{
return Grouping::all()->where('group_id', $id);
}
Which works fine in production (hosted env), BUT when I execute it locally it throws and empty array [] unless I modify my Controller function to look like this:
public function index($id)
{
return Grouping::all()->where('group_id', (integer)$id);
}
I have no idea of what is going on in here, and I am tired of making changes all over my Controller to make it work on both environments.
I have searched in several place, but maybe I am using incorrect tokens for my search as I have found nothing.
Any help will be really appreciated.
The problem here is that you're not using the correct set of functions.
When you call Grouping::all(), this is actually returning an Eloquent Collection object with every record in your groupings table. You are then calling the where() method on this Collection. This causes two problems: one, it is horribly inefficient; two, the where() method on the Collection works differently than the where() method on the query builder.
The where() method on the Collection takes three parameters: the name of the field, the value in that field on which to filter, and finally a boolean value to tell it whether or not to do a strict comparison (===) or a loose comparison (==). The third parameter defaults to strict. This strict comparison is why you're having the issue you are having, but I cannot explain why one environment sees $id as an integer and the other doesn't.
The where() method on a query builder object will actually add a where clause to the SQL statement being executed, which is a much more efficient way of filtering the data. It also has more flexibility as it is not limited to just equals comparisons (the second parameter is the comparison operator for the where clause, but will default to "=" if it is left out).
You have two options to fix your issue. You can either pass in false as the third parameter to your where() method in the current code (bad), or you can update the code to actually filter using the query instead of filtering on the entire Collection (good).
I would suggest updating your code to this:
public function index($id) {
return Grouping::where('group_id', '=', $id)->get();
}
In the above code, Grouping::where('group_id', '=', $id) will generate a query builder object that has the given where clause, and then get() will execute the query and return the Collection of results.
I marked #patricus (thanks you, so much!) as the correct answer, for he really pointed me in the right direction to understand that there are some keywords that work differently under different contexts (like get()), but I will also point out, how my 2 confusing points were solved in my case:
The difference in my code between production and Homestead development environments was solved by pointing my Homestead to the production database. I am not sure what was the difference (maybe collation or table format), but it gave me a quick out.
I was trying to filter a list of elements in the database but I was constructing it with the wrong logic for Laravel.
To clear what I refer to in the second point, I was using this code:
Grouping::all(['id', 'name_id', 'product_id', 'ship_id'])->where('name_id', '=', $id);
I thought this could work, because it would be selecting all items, with the selected columns, and then filter those with a where clause. But I was wrong, since, as I found out later, the correct way of writing this is:
Grouping::where('name_id', $id)->select('id', 'name_id', 'product_id', 'ship_id')->get();
This is because I forgot completely that I was assembling the query, not writing the actions I expected the program to do.
This second syntax has more logic, since I specify the filter, then put the columns over what was filtered, and finally execute the query with the get() clause.
Of course, it can also be written the other side around for clearer fluent reading:
Grouping::select('id', 'name_id', 'product_id', 'ship_id')->where('name_id', $id)->get();

DBSet and dynamic sql expressions

So I have Products class that represent the products table.
To get all the records I do:
db.Products.ToList()
And I have a string like this:
String queryString = "mp=5 AND optic=TRUE AND price=500";
My question is how can I use this string to filter Products? Where func only accept lambda expressions..
Thanks
I'm not sure if it's still supported or not, but you can use Dynamic LINQ to allow you to add 'text' based expressions as you require. See:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
http://pranayamr.blogspot.com/2011/04/dynamic-query-with-linq.html
You may also want to think about using a Predicate builder to do the same job more declaratively. There are a few out there, but one that I've used with great success is the albahari one:
http://www.albahari.com/nutshell/predicatebuilder.aspx
hope this helps..
You can execute Raw SQL against the DbSet and return a strong typed list. For detail, please refer to this blog post by EF team.

Resources