I want rewrite sql query to hibernate criteria and I have this problem.
It is original:
if (null != filterGroupIds && !filterGroupIds.isEmpty()) {
hqueryText += (requereAnd ? " and " : "") + "(";
requereAnd = true;
if (filterGroupIds.contains("null")) {
hqueryText += " w.crmUser.groupId = null ";
filterGroupIds.remove("null");
hqueryText += filterGroupIds.isEmpty() ? "" : "or";
}
if (!filterGroupIds.isEmpty())
hqueryText += " w.crmUser.groupId in (" + StringUtils.join(filterGroupIds.iterator(), ",") + ")";
hqueryText += ")";
}
It is my criteria:
if (null != filterGroupIds && !filterGroupIds.isEmpty()) {
if (filterGroupIds.contains(Integer.valueOf(-1))) {
criteria.add(Restrictions.eq("crmUser.groupId", null));
filterGroupIds.remove(Integer.valueOf(-1));
if (!filterGroupIds.isEmpty()) {
criteria.add(Restrictions.or(Restrictions.in("crmUser.groupId", filterGroupIds)));
}
}else {
criteria.add(Restrictions.in("crmUser.groupId", filterGroupIds));
}
}
but my OR Restrictions not work.
You should be getting compile time error for
criteria.add(Restrictions.or(Restrictions.in("crmUser.groupId", filterGroupIds)));
as Restrictions.or() takes two criterion values.Recheck your code and pass two criterion object to be compared.
Related
I don't understand why in this code, it's do that:
query.setString("idFamilleDeProduit", String.valueOf(familleDeProduits.getFamilleDeProduitsGenerique().getId()));
When I looked my table in my database, id column is integer.
it's PostgreSql-9.4.1207
my function:
public List<ContratMdd> recherchePourDuplication(String typeAccord, FamilleDeProduitsNomenclature familleDeProduits, SocieteInterne societeInterne, SocieteExterne societeExterne, String anneeAccord) throws PersistenceException {
List<ContratMdd> listContratMdd = new ArrayList<ContratMdd>();
String requete = "";
if (!"".equals(anneeAccord)){
requete += " anneeAccord = :anneeAccord";
}
if (!"".equals(typeAccord) && ! "".equals(requete)){
requete += " AND";
}
if (!"".equals(typeAccord)){
requete += " type = :type";
}
boolean existFamille = false;
requete += (familleDeProduits != null && familleDeProduits.getFamilleDeProduitsGenerique() != null) ? " AND " : "";
if(familleDeProduits != null && familleDeProduits.getFamilleDeProduitsGenerique() != null){
existFamille = true;
requete += " estAppliqueSur.familleDeProduitsGenerique IS NOT NULL AND estAppliqueSur.familleDeProduitsGenerique.id = :idFamilleDeProduit";
}
boolean existSocieteInterne = false;
boolean existSocieteExterne = false;
requete += (societeInterne != null) ? " AND " : "";
if(societeInterne != null){
existSocieteInterne = true;
String table = societeInterne instanceof Master ? "MasterImpl" : "AdherentImpl";
requete += " contractantInterne.id = :idsocieteInterne AND contractantInterne IN (FROM "+table+") ";
}
requete += (societeExterne != null) ? " AND " : "";
if(societeExterne!=null){
existSocieteExterne = true;
String table = societeExterne instanceof GroupeIndustriel ? "GroupeIndustrielImpl" : "FournisseurImpl";
requete += " contractantExterne.id = :idsocieteExterne AND contractantExterne IN (FROM "+table+") ";
}
if (!"".equals(requete)) {
requete = "from ContratMddImpl where" + requete;
Query query = createQuery(requete);
if (!"".equals(anneeAccord)){
query.setBigInteger("anneeAccord", new BigInteger(anneeAccord));
}
if (!"".equals(typeAccord)){
query.setString("type", typeAccord);
}
if(existFamille){
query.setString("idFamilleDeProduit", String.valueOf(familleDeProduits.getFamilleDeProduitsGenerique().getId()));
}
if (existSocieteInterne){
query.setInteger("idsocieteInterne", societeInterne.getId());
}
if (existSocieteExterne){
query.setInteger("idsocieteExterne", societeExterne.getId());
}
listContratMdd.addAll((List<ContratMdd>) query.list());
}
return listContratMdd;
}
It is happening because the Postgre's DB Driver allows it. But you should be using setInt() instead of setString() for an Integer as other DB Drivers might not support it.
Here is what java.sql.PreparedStatement Documentation has to say:
Note: The setter methods (setShort, setString, and so on) for setting
IN parameter values must specify types that are compatible with the
defined SQL type of the input parameter. For instance, if the IN
parameter has SQL type INTEGER, then the method setInt should be used.
I'm generating an SQL statement by checking if each of the column fields submitted to the query are empty (== null) or not. It seems that my approach is pretty naive so I'm wondering what can be done about handling null parameters elegantly. When something isn't specified it should simply match anything.
Here is the code:
public List<Flight> findMatchingFlights(Flight flight)
{
List<Flight> foundFlights = new ArrayList<>();
StringBuilder sqlQueryBuilder = new StringBuilder();
sqlQueryBuilder.append("SELECT * FROM Flights");
boolean emptyQuery = true;
if(flight.getDeparture() != null)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
emptyQuery = false;
}
sqlQueryBuilder.append("Departure = '" + flight.getDeparture() + "'");
}
if(flight.getArrival() != null)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
emptyQuery = false;
}
else
{
sqlQueryBuilder.append(" AND ");
}
sqlQueryBuilder.append("Arrival = '" + flight.getArrival() + "'");
}
if(flight.getFlightNumber() != null)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
emptyQuery = false;
}
else
{
sqlQueryBuilder.append(" AND ");
}
sqlQueryBuilder.append("Number = '" + flight.getFlightNumber() + "'");
}
if(flight.getFlightMinutes() != 0)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
emptyQuery = false;
}
else
{
sqlQueryBuilder.append(" AND ");
}
sqlQueryBuilder.append("Duration = " + flight.getFlightMinutes());
}
/*
...
A bunch more fields
*/
if(flight.getAirplane() != null)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
}
else
{
sqlQueryBuilder.append(" AND ");
}
sqlQueryBuilder.append("Airplane = '" + flight.getAirplane() + "'");
}
sqlQueryBuilder.append(";");
// Execute sql and fill list with rows that match
}
You can create the common method for the below block and call the method by passing the arguments.
if(flight.getArrival() != null)
{
if(emptyQuery)
{
sqlQueryBuilder.append(" WHERE ");
emptyQuery = false;
}
else
{
sqlQueryBuilder.append(" AND ");
}
sqlQueryBuilder.append("Arrival = '" + flight.getArrival() + "'");
}
Best approach would be to do the trick in SQL than checking for null in Java. This is how you can do it.
sqlQueryBuilder.append("(Number = '" + flight.getFlightNumber() + "' OR " + flight.getFlightNumber() + " IS NULL)");
This way you wont have to check null in java, if the flight.getFlightNumber() is null then this where clause will always return true which is what you would want.
The only drawback to this method is that the clause will be included in the query, but since you are intending to use these columns to query the table incase they are not null, i would assume the table would be indexed likewise.
sqlQueryBuilder.append("SELECT * FROM Flights WHERE 1 = 1");
then you don't need emptyQuery flag and checks and many if else constractions.
List<Flight> foundFlights = new ArrayList<>();
StringBuilder sqlQueryBuilder = new StringBuilder();
sqlQueryBuilder.append("SELECT * FROM Flights WHERE 1 = 1");
if(flight.getDeparture() != null) {
sqlQueryBuilder.append("AND Departure = '" + flight.getDeparture() + "'");
}
I have successfully created a:
Gridx using JSONStore
Server-side paging using 'Range : items=0-99' header
Server-side sorting using 'sort(+name)'
... but after much effort and searching I haven't been able to setup the Filterbar module to perform Server-side filtering.
I have used 'filterSetupQuery' to pull information out of JSON (on the client) and append to the get URL for very basic filters, but with complicated filters it seems to make more sense to process the JSON in the Java based controller on the server.
What would this Java class and FlexJson deserializer even look like?
Does someone have a reference implementation of Server-side filtering, or even an example to show how to deserialize this object in Java?
Here is a simple JSON object that is sent back to the controller:
{ "op":"and",
"data":[{ "op":"or",
"data":[{"op":"contain","data":[{"op":"string","data":"1","isCol":true},
{"op":"string","data":"john"}]},
{"op":"contain","data":[{"op":"string","data":"2","isCol":true},
{"op":"string","data":"john"}]},
{"op":"contain","data":[{"op":"string","data":"3","isCol":true},
{"op":"string","data":"john"}]},
{"op":"contain","data":[{"op":"string","data":"4","isCol":true},
{"op":"string","data":"john"}]}
]}]}
Any help is greatly appreciated!
Thank you
Chris
You can check gridx source code.. Under \tests\test_grid_filter_serverside.html
filterSetupFilterQuery: function(expr){
var toExpr = function(expr){
if(!expr){ return ""; }
if(typeof expr.data != "object"){
if(expr.isCol){
return "column(\"" + expr.data + "\")";
}
return "\"" + expr.data + "\"";
}else{
var exprs = [];
for(var i in expr.data){
exprs.push(toExpr(expr.data[i]));
}
var op = expr.op;
if(expr.op == "and"){
op = "logicand";
}
if(expr.op == "or"){
op = "logicor";
}
return op + "(" + exprs.join(",") + ")";
}
};
console.log("expr is: ", expr);
var newExpr = toExpr(expr);
if(newExpr){ newExpr += ";"}
console.log("expr is: ", newExpr);
return {query: newExpr};
},
, the function above outputs something like ..
logicor(logicor(contain(column("1"),"drawal"),contain(column("2"),"drawal"),contain(column("3"),"drawal"),contain(column("4"),"drawal"),contain(column("5"),"drawal"),contain(column("6"),"drawal"),contain(column("7"),"drawal")));
I was able to change the function to output sql as below
var toExpr = function(expr) {
if (!expr) {
return "";
}
if ( typeof expr.data != "object") {
if (expr.isCol) {
return cols.item(expr.data);
// return "column(\"" + expr.data + "\")";
}
return "\"" + expr.data + "\"";
} else {
var exprs = [];
for (var i in expr.data) {
exprs.push(toExpr(expr.data[i]));
}
var op = expr.op;
if (op == 'not') {
return "(" + exprs[0].replace(/=/, '<>').replace(/like/, ' not like ') + ")";
}
if (op == 'contain') {
return "(" + exprs[0] + ' like ' + exprs[1].replace(/^"/, '"%').replace(/"$/, '%"') + ")";
}
if (op == 'startWith') {
return "(" + exprs[0] + ' like ' + exprs[1].replace(/^"/, '"%') + ")";
}
if (op == 'endWith') {
return "(" + exprs[0] + ' like ' + exprs[1].replace(/"$/, '"%') + ")";
}
return "(" + exprs.join(" " + op.replace(/equal/, '=') + " ") + ")";
}
};
var newExpr = toExpr(expr);
if (newExpr) {
newExpr += ";";
}
console.log("expr is: ", newExpr);
Hi I'm trying to filter records on the basis of Brand,Flavor,Price,Size,Type. i am using a single form to handle this so if user filter only by brand then rest of options like price,flavor will be unchecked so i am checking if Brand or flavor or price is null.I got the solution but i have make lot of comparisons for all cases. i need a solution by which i have make less comparisons.I am using following code
public List<Products> Filter_Items(String[] Brand, String[] Flavour,Float Price,String Size,String Type)
{
ResultSet rs;
List<Products> data = null;
PreparedStatement stmt;
try {
StringBuilder param = new StringBuilder();
if (Brand != null) {
for (String str : Brand) {
param.append("'").append(str).append("', ");
}
}
StringBuilder param1 = new StringBuilder();
if (Flavour != null) {
for (String str : Flavour) {
param1.append("'").append(str).append("', ");
}
}
String prm = param.toString().length() > 2 ? param.toString()
.substring(0, param.toString().length() - 2) : null;
String prm1 = param1.toString().length() > 2 ? param1.toString()
.substring(0, param1.toString().length() - 2) : null;
String query = "select * from products where ";
if (prm != null && prm1 != null) {
query += "Brand in (" + prm + ") and Flavour in (" + prm1 + ")";
} else if (prm != null && prm1 == null) {
query += "Brand in (" + prm + ")";
} else if (prm1 != null && prm == null) {
query += "Flavour in (" + prm1 + ")";
}
stmt = DataBaseConnection.DBConn.getConnection().prepareStatement(query);
rs = stmt.executeQuery();
if (rs != null) {
data = new ArrayList<Products>();
while (rs.next()) {
Products p = new Products();
p.setTitle(rs.getString("Ttile"));
p.setCategory(rs.getString("Category"));
p.setSubCategory(rs.getString("SubCategory"));
p.setSubCategoryTwo(rs.getString("SubCategorytwo"));
p.setPrice(rs.getInt("Price"));
p.setFlavour(rs.getString("Flavour"));
p.setSize(rs.getString("Size"));
p.setImage(rs.getString("image"));
p.setBrand(rs.getString("Brand"));
p.setInstock(rs.getString("instock"));
p.setInstockQty(rs.getInt("instockqty"));
data.add(p);
}
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
return null;
}
return data;
}
}
You can use as always third party libraries for validation like javax validation or any other more specialized on this.
You could create a bean of your data with all the getters and setters and apply validation on your bean.
To pass arrays you need getters and setters like this one:
public class Foo {
private int[] array;
public Foo(int[] array) {
this.array = Arrays.copyOf(array, array.length);
}
/** #param the array to use */
public setArray(int[] array) {
this.array = Arrays.copyOf(array, array.length);
}
/** #return a copy of the array */
public int[] getArray() {
return Arrays.copyOf(array, array.length);
}
}
To validate a bean see this tutorial.
What you really need is to start naming variables according to what they are logically. Names like prm and prm1 are meaningless, while brand and flavor make more sense as variable names since that's what's in them.
I don't see the number of comparisons as a problem. But giving everything generic variable names and then not even indenting the if-statements makes my eyes glaze over.
How about something like this:
if (brand != null && flavor != null)
{
query += "Brand in (" + brand + ") and Flavour in (" + flavor + ")";
}
else if (brand != null && flavor == null)
{
query += "Brand in (" + brand + ")";
}
else if (flavor != null && brand == null)
{
query += "Flavour in (" + flavor + ")";
}
Edit: One thing you can do is split your SQL into two variables, one for the main query and one for the where clause, then just add to the where clause like this:
private String addToWhereClause(String currentWhereClause, String fieldname, String value)
{
String returnValue = "";
if (value != null)
{
if(!"".equals(currentWhereClause))
{
returnValue += " AND ";
}
returnValue += " "+fieldname+" IN(" + value + ") ";
}
return returnValue;
}
String whereClause = "";
whereClause += addToWhereClause(whereClause, "Brand", brand);
whereClause += addToWhereClause(whereClause, "Flavour", flavor);
query = query + " " + whereClause;
So I have this code that checks 4 parameters (author, title, keyword and subject) to do some dynamic sql query generation for a project I'm working on and I was just wondering if anyone knew of a better way to write this out. I get the feeling this is a really inefficient way to do this but it's late and I'm tired. Please let me know if you know of any better way to do this, it's just a bunch of if/else case checking statements at this point.
Thanks!
if(_author!=null)
{
query += authorQ;
if(_title != null)
{
if(conjunct[0] == 0)
{
query += " AND ";
query += titleQ;
}
else
{
query += " OR ";
query += titleQ;
}
if(_keyword != null)
{
if(conjunct[1] == 0)
{
query += " AND ";
query += keywordQ;
}
else
{
query += " OR ";
query += keywordQ;
}
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
else
{
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
}//title = null
else
{
if(_keyword != null)
{
if(conjunct[1] == 0)
{
query += " AND ";
query += keywordQ;
}
else
{
query += " OR ";
query += keywordQ;
}
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
else //keyword null
{
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
//if subject's null at this point we don't care
}
}
}
else //author null
{
if(_title != null)
{
if(conjunct[0] == 0)
{
query += " AND ";
query += titleQ;
}
else
{
query += " OR ";
query += titleQ;
}
if(_keyword != null)
{
if(conjunct[1] == 0)
{
query += " AND ";
query += keywordQ;
}
else
{
query += " OR ";
query += keywordQ;
}
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
else
{
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
}//title = null
else
{
if(_keyword != null)
{
if(conjunct[1] == 0)
{
query += " AND ";
query += keywordQ;
}
else
{
query += " OR ";
query += keywordQ;
}
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
}
else //keyword null
{
if(_subject != null)
{
if(conjunct[2] == 0)
{
query += " AND ";
query += subjectQ;
}
else
{
query += " OR ";
query += subjectQ;
}
}
//if subject's null at this point we don't care
}
}
}
How about a more structured and scalable approach, see example below. By the way, you shouldn't really be putting user input straight into SQL queries - use prepared statements instead to try to guard against injection attacks.
// test values
String _author = "authorfoo";
String _title = "titlebar";
String _keyword = null;
String _subject = "subjectfoo";
String authorQ = "author=" + _author;
String subjectQ = "subject=" + _subject;
String titleQ = "title="+ _title;
String keywordQ = "keyword=" + _keyword;
int conjunct[] = new int[]{ 0, 1, 1, 0};
// query building code
String []inputs = {_author, _title, _keyword, _subject};
String []queries = {authorQ, titleQ, keywordQ, subjectQ};
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < inputs.length; i++) {
if (inputs[i] != null) {
if (builder.length() > 0) { // don't start query with connective
if (conjunct[i] == 0) {
builder.append(" AND ");
} else {
builder.append(" OR ");
}
}
builder.append(queries[i]);
}
}
String query = builder.toString();
System.out.println(query);
a = _author ? authorQ : 1;
t = _title ? titleQ : 1;
k = _keyword ? keywordQ : 1;
s = _subject ? subjectQ : 1;
c1 = conjunct[0] ? " OR " : " AND ";
c2 = conjunct[1] ? " OR " : " AND ";
c3 = conjunct[2] ? " OR " : " AND ";
query += a + c1 + t + c2 + k + c3 + s;