Best way by pass parameter in service layer - spring-mvc

I have a Student info table with column Name, Sex,Class, Course, Grade.. etc
I would like to implement a filter, require search by name, by class,by course,by grade ....
I using mybatis by querying the DB.. the query is very simple. But I have to write multiple query to implement these search function.
Select * FROM TB where name =#{name} ,
Select * FROM TB where class =#{class},
Select * FROM TB where course =#{course},
Select * FROM TB where grade =#{grade}
....
In service layer,
Multiple functions need to implement.
List<Student> getStudentByName(String name);
List<Student> getStudentByCourse(String course);
... bla bla ...
Question:
is that any simple way to implement this requirement?
what I expected is :
in #service layer, a function can handle all the pass parameter,
like:
List search( someParam );
I come out with an idea is using in mybatis.
SELECT * FROM TB WHERE 1 =1
<if name!=null>
AND name = #{name}
</if>
I'm not sure if this is a good practice for approaching.

yes it can
you can do that . refer the below syntax in xml :
SELECT * FROM TB WHERE 1 = 1
<if name != null and name!= ""'>
AND name = #{name}
</if>
<if class != null and class!= ""'>
AND class = #{class}
</if>
<if course != null and course!= ""'>
AND course = #{course}
</if>
<if grade != null and grade != ""'>
AND grade = #{grade}
</if>

Related

Modify query string on a form to add filter based on other fields

I have an enquiry form which works from a view with a custom query. The form has filters, which I use in the executeQuery method of the view on the form to add ranges on various fields.
A new requirement is to filter based on two fields in the query.
Example: The PurchLine table is one of the tables in the query.
A new range is needed :
if PurchLine.ItemId != “” then
filter by PurchLine.PurchStatus == None
but, if the Item has a SPECIFIC value,
then filter by PurchStatus == Received.
(Ok, this is just an example!).
I am unable to modify my query to add a range on the PurchStatus based on the Item field.
I know exactly how the string value of the query must look, but how can I modify the query string?
The current query string looks like this (if I breakpoint on super in executeQuery):
SELECT FIRSTFAST * FROM OpenPOLinesView(OpenPOLinesView) WHERE ((CreatedDateTime<='2016-11-30T23:59:59')) AND ((VendAccount = N'S000001048'))
I want to add this at the end:
AND (((ItemId = N'') AND (PurchStatus = 0)) OR ((ItemId = N'XXX123') AND (PurchStatus = 2)))
How can I modify the query string in code?
You can use query expression for this, e.g.
queryBuildRange.value(strFmt('((%1 == %2) || ((%1 == %3) && (%4 == "%5")))',
fieldStr(InventTable, ItemType),
any2int(ItemType::Service),
any2int(ItemType::Item),
fieldStr(InventTable, ProjCategoryId),
queryValue("Spares")));
Please refer to this link Using Expressions in Query Ranges [AX 2012] for details.

Pass parameter that will return all rows

I'm working on an ASP.NET application that will call a simple Stored Procedure. The SP looks something like this:
Select *
from empTable
where ID = #ID AND Department = #DeptID
and status = #status
and role = #role
The ASP.NET application will pass a value to the each parameter in the stored procedure. Every parameter can be null or have a value. However, if the user enter nothing (null or empty), it should return everything in that empTable as if Select * from empTable with no Where clause.
However, due to the orders from the management:
I CANNOT change the code in ASP.NET application.
I CANNOT use dynamic SQL.
I'm only allowed to modify the stored procedure.
Is there any way I can work around this?
Make the parameter optional by changing the WHERE clause and assign a default value.
CREATE PROCEDURE MyProc
#ID INT = NULL
AS
Select * from empTable where ID = ISNULL(#ID, ID);
Case statements work...use case to set 1 = 1 when #id = 'all' (or whatever you want the #id to equal for all)
Select * from empTable where
case when #id = 'all' then 1 else id end
=
case when #id = 'all' then 1 else #id
JodyT's answer is better...this works, but not as pretty

Cannot implicitly convert type 'System.Data.Linq.ISingleResult<CustomeProcedureName> to 'int'

Sorry for this simple question .
I have a Stored Procedure that return an int value , I'm trying to call this sp from my asp.net linq to sql project .
int currentRating = db.sproc_GetAverageByPageId(pageId);
But i get this error :
Cannot implicitly convert type `'System.Data.Linq.ISingleResult<PsychoDataLayer.sproc_GetAverageByPageId> to 'int' .`
Edit 1
The solution that friends implied didn't work . All the time it return 0
For more information i put my stored procedure here :
ALTER procedure [dbo].[sproc_GetAverageByPageId](
#PageId int )
as
select (select sum(score) from votes where pageId = #PageId)/(select count(*) from votes where pageId=#PageId)
You should inspect the ReturnValue property.
Perhaps the following works better?
int currentRating = (int)db.sproc_GetAverageByPageId(pageId).ReturnValue;
Update: since your stored proc returns a resultset instead of using a return statement the actual data will be available as an element in the enumerable returned by db.sproc_GetAverageByPageId(pageId). If you inspect the ISingleResult<T> type, you'll see that it inherits IEnumerable<T> which indicates that you can enumerate the object to get to the data, each element being of type T.
Since the sproc does a SELECT SUM(*) ... we can count on the resultset to always contain one row. Thus, the following code will give you the first (and only) element in the collection:
var sumRow = db.sproc_GetAverageByPageId(pageId).Single();
Now, the type of sumRow will be T from the interface definition, which in your case is PsychoDataLayer.sproc_GetAverageByPageId. This type hopefully contains a property that contains the actual value you are after.
Perhaps you can share with us the layout of the PsychoDataLayer.sproc_GetAverageByPageId type?
Looks like you're actually after the ReturnValue. You may need to cast it to System.Data.Linq.ISingleResult if it isn't already, then cast ReturnValueto int.
This is actually returning an ISingleResult
int currentRating = (int) db.sproc_GetAverageByPageId(pageId).ReturnValue;
Change your sp to :
ALTER procedure [dbo].[sproc_GetAverageByPageId](
#PageId int )
as
return (select sum(score) from votes where pageId = #PageId)/(select count(*) from votes where pageId=#PageId)
one more thing you can do:
ALTER procedure [dbo].[sproc_GetAverageByPageId](#PageId int ) as
select (select sum(score) from votes where pageId = #PageId)/(SELECT * FROM votes where pageId=#PageId)
WRITE >>
"select * From"<< instead of "select Count(*)"
select (select sum(score) from votes where pageId = #PageId)/(SELECT * FROM votes where pageId=#PageId)
and after that:
int currentRating = (int)db.sproc_GetAverageByPageId(pageId).count();

Passing a IS NOT NULL through a sqlparameter

I have a query in sql server 2008. That I want to either pass a value from the dropdownlist or IS NOT NULL (so it shows all of the values). What's the best way to handle this? I know you can't pass the string "IS NOT NULL" to the parameter. I'm a bit stuck on this one.
ASP.NET 3.5 and SQL Server 2008.
Assuming this is a stored procedure, say your parameter is called #Param1, have the parameter set to NULL to indicate IS NOT NULL, as follows:
SELECT ...
FROM ...
WHERE (
(#Param1 IS NULL AND field1 IS NOT NULL)
OR (field1 = #Param1)
)
Suggested by GSerg
Testing ISNULL(#Param1, field1) = field1 with the following:
DECLARE #test1 nvarchar(10) = 'testing',
#test2 nvarchar(10) = NULL; -- or 'random' or 'testing'
SELECT 1
WHERE ISNULL(#test2, #test1) = #test1;
Computations are showing as 1 for each case. This appears to be a better solution than my original answer.
You can use the like operator:
select * from table1 where name like #param
setting #param to % if you want not null values. But then you have to escape the %.

Entity Framework - joining nulls - NullReferenceException was unhandled by user code

I am writing an asp.net mvc application to learn Entity Framework with and am running into an issue that I do not know how to handle. For simplicity lets take the following table structure:
Movie
ID (int, not null, auto increment)
Name (varchar)
GenreID (int)
and
Genre
ID (int, not null, auto increment)
Name (varchar)
Movie.GenreID is a FK reference to Genre.ID
I have brought across all of the tables using the visual designer in VS 2008 and tried the following Linq query:
IEnumerable<Movie> movieList = from f in dataContext.MovieSet.Include("Genre").ToList();
I can output the data in a view using:
<%= Html.Encode( movieList.Genre.Name ) %>
Everything works just fine until I have an item in the Movie table with a null GenreID. Is there something I can do to this query to make it still be able to output (just leave it blank when applicable) or am I doing something horribly wrong?
The problem is that movieList.Genre is null, and you can't access the Name property of a null object.
You can solve this by writing <%= Html.Encode(movieList.Genre == null ? String.Empty : movieList.Genre.Name) %>.
If you don't want your views to be so verbose, you could add a GenreName property to the Movie entity class and move the null check there.
This is probably much more readable than .Include("")
from f in dataContext.MovieSet
select new
{
Name = f.Name,
Genre = f.Genre // This effectively performs a join.
...
}
You can also check for the problem that way:
from f in dataContext.MovieSet
select new
{
Name = f.Name,
GenreName = f.Genre == null ? "" : f.Genre.Name
...
}
This gives you more flexibility, for instance:
from f in dataContext.Genres
select new
{
Name = f.Name
Movies = from movie in f.Movies
where movie.Duration > 240
select movied
}

Resources