Java, CriteriaBuilder, query with optional parameter "where" - java

I have to rewrite some code, but couldn't find proper information on the Internet. The original part looks like this:
String query = "select * from sublog_type_map_v where 1 = 1";
if (responsibleGroupId != null && responsibleGroupId.length() != 0 && !responsibleGroupId.equals("0")) {
query += " and responsible_group_id = " + responsibleGroupId;
}
if (categoryId != null && categoryId.length() != 0 && !categoryId.equals("0")) {
query += " and category_id = " + categoryId;
}
if (typeId != null && typeId.length() != 0 && !typeId.equals("0")) {
query += " and type_id = " + typeId;
}
if (subtypeId != null && subtypeId.length() != 0 && !subtypeId.equals("0")) {
query += " and subtype_id = " + subtypeId;
}
And I've proceeded to this code:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<SublogTypeMapV> query = builder.createQuery(SublogTypeMapV.class);
Root<SublogTypeMapV> root = query.from(SublogTypeMapV.class);
query.select(root).where(builder.equal(root.get("responsibleGroupId"), responsibleGroupId));
But this "where" should be considered optional using "if" expression, as well as the other three parameters (which I will add later). I have no earthly idea how to do it, could anyone help me out?

I guess this will do the needful -
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<SublogTypeMapV> query = builder.createQuery(SublogTypeMapV.class);
Root<SublogTypeMapV> root = query.from(SublogTypeMapV.class);
query = query.select(root);
if("some boolean expression") {
query = query.where(builder.equal(root.get("responsibleGroupId"), responsibleGroupId));
}
Similarily you can handle other conditions inside.

Related

how to set dynamically created where Clause in JPA Criteria Queries,

This is my Jpa Query Criteria...
EntityManagerFactory em;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<SearchUser> cq = cb.createQuery(SearchUser.class);
Root<SearchUser> userRoor = cq.from(SearchUser.class);
cq.select(userRoot);
TypedQuery<SearchUser> query = ((EntityManager) em).createQuery(cq);
List<SearchUser> users = query.getResultList();
This is Where Clause i am creating dynamically...now i want the jpa to search result result according to this dynamically generated where clause...but don't know how to append this where clause with select query... can anybody edit and show me right query please... Thanks in Advance
StringBuilder whereClause = new StringBuilder();
whereClause.append("where ")
if (searchUserDTO.getId() != null) {
whereClause.append("id=" + searchUserDTO.getId());
}
if (searchUserDTO.getFirstName() != null) {
whereClause.append(" and firstName=" + searchUserDTO.getFirstName());
}
if (searchUserDTO.getLastName() != null) {
whereClause.append(" and lastName=" + searchUserDTO.getLastName());
}
if (searchUserDTO.getDateOfBirth() != null) {
whereClause.append(" and dateOfBirth=" + searchUserDTO.getDateOfBirth());
}
if (searchUserDTO.getEmail() != null) {
whereClause.append(" and email=" + searchUserDTO.getEmail());
}

code part I do not understand

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.

Avoid comparison from conditional statements

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;

when running my java code i am facing this error ->

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
my code:
public static void loanenquiry(String ApplicationID,String LoanNumber,String RIMNumber,String custname,String fromdate,String todate) {
String wherestring = "SELECT * FROM bf_loanmaster WHERE";
try {
if(ApplicationID != null) {
wherestring = wherestring + "ApplicationID ="+BillAction.StringtoInt(ApplicationID)+"";
}
if(LoanNumber != null ) {
if(ApplicationID != null) {
wherestring = wherestring + "AND LoanNumber = "+BillAction.StringtoInt(LoanNumber)+" ";
} else {
wherestring = wherestring + "LoanNumber = "+BillAction.StringtoInt(LoanNumber)+" ";
}
}
if(RIMNumber != null ) {
if(ApplicationID != null && LoanNumber != null) {
wherestring = wherestring + "AND AdvparyRIM = "+RIMNumber+" ";
} else {
wherestring = wherestring + "AdvparyRIM = "+RIMNumber+"";
}
}
if(custname != null ){
if(ApplicationID != null && LoanNumber != null && RIMNumber != null ) {
wherestring = wherestring + "AND custName = "+custname+"";
} else {
wherestring = wherestring + "custName = "+custname+"";
}
}
if(fromdate != null ) {
if(ApplicationID != null && LoanNumber != null && RIMNumber != null && custname != null ) {
wherestring = wherestring + "AND ApplicationDt >= "+BillAction.StringtoDate(fromdate)+" ";
} else {
wherestring = wherestring + "ApplicationDt = "+BillAction.StringtoDate(fromdate)+"";
}
}
if(todate != null ) {
if(ApplicationID != null && LoanNumber != null && RIMNumber != null && custname != null && fromdate != null) {
wherestring = wherestring + "AND ApplicationDt >= "+BillAction.StringtoDate(fromdate)+" AND ApplicationDt <= "+BillAction.StringtoDate(todate)+"";
} else {
wherestring = wherestring + "ApplicationDt >= "+BillAction.StringtoDate(todate)+"";
}
}
Connection conn = BillFinanceDB.getDBConnection();
PreparedStatement psloanenquiry= conn.prepareStatement(wherestring + ";");
ResultSet rs = psloanenquiry.executeQuery();
while(rs.next()) {
System.out.println("loan number"+rs.getInt("LoanNumber"));
}
} catch(SQLException e) {
e.printStackTrace();
}
}
Any ideas?
thanks for the help.
My guess: you're missing a space after WHERE in your constructed string. Try this:
String wherestring = "SELECT * FROM bf_loanmaster WHERE ";
The best way to debug these kinds of errors is to print out the SQL query you have constructed before it is executed so that you can manually inspect it for problems.
The WHERE is most likely a problem. The second problem that you could have is not putting your strings in quotation marks. For example it probably should be wherestring = wherestring + "custName = '"+custname+"' ";
Also things to note:
All this appending is terribly inefficient, use a StringBuilder or StringBuffer instead. You could also use PreparedStatements which would make your code perform better and possibly even make it easier to read.
Add a space after where.. You have to seperate keywords like where..
give a space in your query
String wherestring = "SELECT * FROM bf_loanmaster WHERE";
there is no space between WHERE statement and condition.

MYSQL LIMIT not working as expected - Java

I have this weird problem in java when trying to fetch records from MYSql database by using the limit function in the query. Not sure what went wrong or did wrong, this query is giving me a hard time.
Issue - When I run this query through my java program it returns all the records and not limiting the records to 10 as given in the limit.
The same query when ran in MYSql command line, it execute very well and fetches me only 10 recrods.
Below is the java code and query. Any help or support is appreciated.!
Java code -
public UserVO getApplUserDetailsList(UserVO userVO) throws CAPDAOException {
List<UserVO> returnList = null;
String methodName = "getApplUserDetails()";
Session session = null;
String queryString = null;
Transaction transaction = null;
PreparedStatement ps = null;
ResultSet rs = null;
if(userVO == null)
{
logger.writeToTivoliAlertLog(className, CAPConstants.ERROR, methodName, null, "userVO returned null. Busines validation error.!", null);
throw new CAPDAOException("userVO returned null. Busines validation error.!",CAPException.BUSINESS_VALIDATION_ERROR_SECURITY);
}
try {
returnList = new ArrayList<UserVO>();
System.out.println("");
String appusr = userVO.getAppUsrNm();
session = getSession();
transaction = session.beginTransaction();
if(userVO.getAppUsrRoleCd()!=null && !userVO.getAppUsrRoleCd().trim().equalsIgnoreCase(CAPConstants.DEFAULT_DROPDOWN_VALUE)){
queryString = "SELECT " +
"APPL_USR_ID,APPL_USR_NM,APPL_USR_FRST_NM, " +
"APPL_USR_LST_NM,ACCESS_ROLE_CD " +
"FROM APPL_USR " +
"WHERE " +
"APPL_USR_NM LIKE ?"+
" AND APPL_USR_FRST_NM LIKE ?"+
" AND APPL_USR_LST_NM LIKE ?"+
" AND ACCESS_ROLE_CD = ?"+
" AND APPL_USR_ID != ?";
ps = session.connection().prepareStatement(queryString);
ps.setString(1,userVO.getAppUsrNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setString(2,userVO.getAppUsrFirstNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setString(3,userVO.getAppUsrLastNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setString(4,userVO.getAppUsrRoleCd());
ps.setInt(5, 1);
}
else
{
queryString = "SELECT " +
"APPL_USR_ID,APPL_USR_NM,APPL_USR_FRST_NM, " +
"APPL_USR_LST_NM,ACCESS_ROLE_CD " +
"FROM APPL_USR " +
"WHERE " +
"APPL_USR_NM LIKE ?"+
" AND APPL_USR_FRST_NM LIKE ?"+
" AND APPL_USR_LST_NM LIKE ?"+
" AND APPL_USR_ID != ?";
ps = session.connection().prepareStatement(queryString);
ps.setString(1,userVO.getAppUsrNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setString(2,userVO.getAppUsrFirstNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setString(3,userVO.getAppUsrLastNm()+CAPConstants.PERCENTILE_SYMBOL);
ps.setInt(4, 1);
}
if(userVO.getQueryAction()!=null && userVO.getQueryAction().equals(CAPConstants.GET_DATA))
queryString += " ORDER BY APPL_USR_ID LIMIT " + userVO.getPAGE_MIN_LIMIT() + ", " + userVO.getPAGE_MAX_LIMIT();
else
queryString += " ORDER BY APPL_USR_ID";
rs = ps.executeQuery();
if(userVO.getQueryAction()!=null && userVO.getQueryAction().equals(CAPConstants.GET_DATA))
{
int tempCOunt = 0;
while(rs!=null && rs.next())
{
tempCOunt ++;
UserVO returnVO = new UserVO();
returnVO.setAppUsrId(rs.getInt("APPL_USR_ID"));
returnVO.setAppUsrNm(rs.getString("APPL_USR_NM"));
returnVO.setAppUsrFirstNm(rs.getString("APPL_USR_FRST_NM"));
returnVO.setAppUsrLastNm(rs.getString("APPL_USR_LST_NM"));
if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.ADMINISTRATOR_ROLE_CD))
returnVO.setApplicationLevelRole("Administrator");
else if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.MAINTAINER_ROLE_CD))
returnVO.setApplicationLevelRole("Maintainer");
else if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.VIEWER_ROLE_CD))
returnVO.setApplicationLevelRole("Viewer");
else
returnVO.setApplicationLevelRole("None");
returnList.add(returnVO);
}
System.out.println("Count >>>>>>>>>>>>>>>>>>> "+tempCOunt);
userVO.setReturnListFromDB(returnList);
}
else
{
int rowcount = 0;
if (rs.last()) {
rowcount = rs.getRow();
rs.beforeFirst(); // not rs.first() because the rs.next() below will move on, missing the first element
}
userVO.setTotalRecordCount(rowcount);
System.out.println("Total count of the records to be used for pagination >> "+rowcount);
rowcount = 0;
while(rs!=null && rs.next())
{
rowcount ++;
UserVO returnVO = new UserVO();
returnVO.setAppUsrId(rs.getInt("APPL_USR_ID"));
returnVO.setAppUsrNm(rs.getString("APPL_USR_NM"));
returnVO.setAppUsrFirstNm(rs.getString("APPL_USR_FRST_NM"));
returnVO.setAppUsrLastNm(rs.getString("APPL_USR_LST_NM"));
if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.ADMINISTRATOR_ROLE_CD))
returnVO.setApplicationLevelRole("Administrator");
else if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.MAINTAINER_ROLE_CD))
returnVO.setApplicationLevelRole("Maintainer");
else if (rs.getString("ACCESS_ROLE_CD")!=null && rs.getString("ACCESS_ROLE_CD").trim().equalsIgnoreCase(CAPConstants.VIEWER_ROLE_CD))
returnVO.setApplicationLevelRole("Viewer");
else
returnVO.setApplicationLevelRole("None");
returnList.add(returnVO);
System.out.println("Row count >>"+rowcount);
if(rowcount == CAPConstants.PAGINATION_MAX_VALUE)
break;
}
rowcount = 0;
userVO.setReturnListFromDB(returnList);
}
System.out.println("returnList >>"+returnList);
return userVO;
} catch (Throwable e) {
e.printStackTrace();
logger.writeToTivoliAlertLog(className, CAPConstants.ERROR, methodName, userVO.getAppUsrNm(), "Error occured while trying to fetch application user details. Printing stack trace to the log for analysis..", e);
throw new CAPDAOException("Error occured while trying to fetch application user details.",CAPException.SPEXECUTION_ERROR_CODE);
}
finally{
closeTransactionAndSession(session,transaction);
}
}
MYSQL Query -
SELECT APPL_USR_ID,APPL_USR_NM,APPL_USR_FRST_NM, APPL_USR_LST_NM,ACCESS_ROLE_CD
FROM APPL_USR WHERE APPL_USR_NM LIKE '%'
AND APPL_USR_FRST_NM LIKE '%'
AND APPL_USR_LST_NM LIKE '%'
AND APPL_USR_ID != 1
ORDER BY APPL_USR_ID
LIMIT 10, 10
you add your LIMIT after
ps = session.connection().prepareStatement(queryString);
so when calling
rs = ps.executeQuery();
the LIMIT is not in there.
So, call prepareStatement when the queryString construction is finished.
You are changing the querystring after you have prepared the statement with the string.

Categories

Resources