Spring jdbcTemplate dynamic where clause - spring

Is it possible to generate arbitrary where condtions SQL query through Jdbc template:
example:
If i pass value for 1 parameter (only name) : search by name
"select * from address where shopname = ?";
If i pass value for 2 parameter (name and city) - search by shopname and city:
"select * from address where shopname = ? and city = ?";
I have mupliple search fields. 7 fields. If user enters any combination. i have search only based on parameter. How to dynamically pass the parameters to the sql. Need snippet/Example how to achieve this.

What you want is some sort of criteria building api, which Hibernate has. Unfortunately, I don't think Spring's JdbcTemplate has any such facility. Others will correct me if I'm wrong...

Though as some guys already suggested that Hibernate is the best way of doing this, but still i think you can try this approach-
String sql = "select * from address where 1 = 1";
if(shopname != null)
sql += "and shopname = :shopname";
if(city!= null)
sql += "and city = :city";
and so on..and use NamedParameterJdbcTemplate

Spring Data and Hibernate have that kind of functionality. Though it might not be worth dragging in such big framework for your app.
You can try to check out SimpleJdbcInsert
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html
Edit:
Alternatively you can try to fix it in SQL with checking on empty, but if you have lots of data to go through, this technique will slow down your request.
"select * from address
where (shopname = ? or shopname = null)
and (city = ? or city = null)";

If Scala is an option to you, the query could be constructed with something like this:
case class Search(shopname:String, city:String = None) {
def sql = "select * from address where shopname = '"+shopname+"'" + city.map(" and city = '"+
_ +"'").getOrElse("")
}
Example usage:
Search("lloh").sql
Search("lloh", Some("Austin")).sql

Related

Is it possible to dynamic query to stored procedure?

I have a Spring boot application. I need a feature to dynamically query the stored procedure. What I mean by dynamically,
#NamedNativeQuery(name = "getCustomFoo", query = "select * from SP_FOO_CUSTOM where id = 1", resultClass = Foo.class)
but id could be any attribute in result set, so it could change based on the users input;
#NamedNativeQuery(name = "getCustomFoo", query = "select * from SP_FOO_CUSTOM where fooid = 1 ", resultClass = Foo.class)
Is it possible to do something like this? or this is totally out of standards?

generic hql select function given field and param

is this valid HQL?
If not (i assume not since im getting wrong result back). How/can i achieve this generic slect transaction?
String hql = "SELECT * from users Where :searchCriteria = :searchString";
List q = session.createSQLQuery(hql).addEntity(Users.class)
.setParameter("searchField", searchCriteria)
.setParameter("searchString", searchString).list();
Try this hql,
Criteria cr= session.createCriteria(Users.class);
cr.add(Restrictions.eq("searchField", searchCriteria);
cr.add(Restrictions.eq("searchString", searchString);
List<Users> user_data=(List<Users>)cr.list();

How Could I Convert Text to Entity Frameworks Query

I need to store user queries in a database. The queries will then run against an entity frameworks structure. So an example would be :
using(AdventureWorksDB aw = new
AdventureWorksDB(Settings.Default.AdventureWorks)) {
var newSalesPeople = from p in aw.SalesPeople
where p.HireDate > hireDate
orderby p.HireDate, p.FirstName
select new { Name = p.FirstName + " " + p.LastName,
HireDate = p.HireDate };
foreach(SalesPerson p in newSalesPeople) {
Console.WriteLine("{0}\t{1}", p.FirstName, p.LastName);
}
}
How could I convert the above, if it was stored as text, to become an entity framework query that gets run? Also is there another recommended way of storing the query eg xml
Thanks for reading
It appears ObjectContext.CreateQuery is the best solution. As it says it enables for queries to be added to a context at runtime - http://msdn.microsoft.com/en-us/library/bb339670(v=vs.110).aspx . Also, storing the queries as a string in a database would be perfectly adequate.

Help required to optimize LINQ query

I am looking to optimize my LINQ query because although it works right, the SQL it generates is convoluted and inefficient...
Basically, I am looking to select customers (as CustomerDisplay objects) who ordered the required product (reqdProdId), and are registered with a credit card number (stored as a row in RegisteredCustomer table with a foreign key CustId)
var q = from cust in db.Customers
join regCust in db.RegisteredCustomers on cust.ID equals regCust.CustId
where cust.CustomerProducts.Any(co => co.ProductID == reqdProdId)
where regCust.CreditCardNumber != null && regCust.Authorized == true
select new CustomerDisplay
{
Id = cust.Id,
Name = cust.Person.DisplayName,
RegNumber = cust.RegNumber
};
As an overview, a Customer has a corresponding Person which has the Name; PersonID is a foreign key in Customer table.
If I look at the SQL generated, I see all columns being selected from the Person table. Fyi, DisplayName is an extension method which uses Customer.FirstName and LastName. Any ideas how I can limit the columns from Person?
Secondly, I want to get rid of the Any clause (and use a sub-query) to select all other CustomerIds who have the required ProductID, because it (understandably) generates an Exists clause.
As you may know, LINQ has a known issue with junction tables, so I cannot just do a cust.CustomerProducts.Products.
How can I select all Customers in the junction table with the required ProductID?
Any help/advice is appreciated.
The first step is to start your query from CustomerProducts (as Alex Said):
IQueryable<CustomerDisplay> myCustDisplay =
from custProd in db.CustomerProducts
join regCust in db.RegisteredCustomers
on custProd.Customer.ID equals regCust.CustId
where
custProd.ProductID == reqProdId
&& regCust.CreditCardNumber != null
&& regCust.Authorized == true
select new CustomerDisplay
{
Id = cust.Id,
Name = cust.Person.Name,
RegNumber = cust.RegNumber
};
This will simplify your syntax and hopefully result in a better execution plan.
Next, you should consider creating a foreign key relationship between Customers and RegisteredCustomers. This would result in a query that looked like this:
IQueryable<CustomerDisplay> myCustDisplay =
from custProd in db.CustomerProducts
where
custProd.ProductID == reqProdId
&& custProd.Customer.RegisteredCustomer.CreditCardNumber != null
&& custProd.Customer.RegisteredCustomer.Authorized == true
select new CustomerDisplay
{
Id = cust.Id,
Name = cust.Person.Name,
RegNumber = cust.RegNumber
};
Finally, for optimum speed, have LINQ compile your query at compile time, rather than run time by using a compiled query:
Func<MyDataContext, SearchParameters, IQueryable<CustomerDisplay>>
GetCustWithProd =
System.Data.Linq.CompiledQuery.Compile(
(MyDataContext db, SearchParameters myParams) =>
from custProd in db.CustomerProducts
where
custProd.ProductID == myParams.reqProdId
&& custProd.Customer.RegisteredCustomer.CreditCardNumber != null
&& custProd.Customer.RegisteredCustomer.Authorized == true
select new CustomerDisplay
{
Id = cust.Id,
Name = cust.Person.Name,
RegNumber = cust.RegNumber
};
);
You can call the compiled query like this:
IQueryable<CustomerDisplay> myCustDisplay = GetCustWithProd(db, myParams);
I'd suggest starting your query from the product in question, e.g. something like:
from cp in db.CustomerProducts
join .....
where cp.ProductID == reqdProdID
As you have found, using a property defined as an extension function or in a partial class will require that the entire object is hydrated first and then the select projection is done on the client side because the server has no knowledge of these additional properties. Be glad that your code ran at all. If you were to use the non-mapped value elsewhere in your query (other than in the projection), you would likely see a run-time exception. You can see this if you try to use the Customer.Person.DisplayName property in a Where clause. As you have found, the fix is to do the string concatenation in the projection clause directly.
Lame Duck, I think there is a bug in your code as the cust variable used in your select clause isn't declared elsewhere as a source local variable (in the from clauses).

Get Row Count InvalidCast Exception from ScalarQuery

ScalarQuery<int> query = new ScalarQuery<int>(typeof(Role),
"select count(role.RoleId) from Role as role");
return query.Execute();
It fails with the invalidcast exception but succeeds when count is replaced with max.
Edit: Some databases will return long for count queries. For example SQL Server.
ScalarQuery<long> query = new ScalarQuery<long>(typeof(Role),
"select count(r) from Role r");
return query.Execute();
What database are you using? Could be that count does not return an int.
Your could also try using http://api.castleproject.org/html/T_Castle_ActiveRecord_Queries_CountQuery.htm
Not exactly the answer to the question, but a recommendation: if you want to avoid the hassle of having to issue a query at all yourself, then just use ActiveRecordMediator<T>.Count() (which has overloads that take criteria / filter strings if you want a conditional count) and all return int against all databases.
Based on testing the answers given to date, the following worked for me (including a where clause):
// Option 1
int result = ActiveRecordMediator<Post>.Count("BlogId = ?", blogId);
// Option 2
CountQuery query = new CountQuery(typeof(Post), "BlogId = ?", blogId);
int result = ActiveRecordMediator.ExecuteQuery(query);
// Option 3
ScalarQuery<long> query= new ScalarQuery<long>(typeof(Post),
"SELECT COUNT(*) FROM Post WHERE BlogId = ?", blogId);
long result = query.Execute();

Resources