How can I get rid of a trailing AND in Java - java

This is a dumb question, but how can I delete a trailing AND in a sql statement in Java?
I'm dynamically generating the statement based on the Profile object I give it. So, if the object has "name = person1" and "address = example road", the statement should be:
select * from Profile where name = 'person1' and address = 'example road'
The issue is that I'm using a for loop to iterate through the declared fields of the object, and so it adds an extra AND to the end:
select * from Profile where name = 'person1' and address = 'example road' and
What would be the best way to get rid of a trailing AND?

You should be using a prepared statement. Building a query like this leaves you open to SQL injection and other attacks.
If you must continue with your current approach, then a quick fix would be to strip off the final AND via regex:
String sql = "select * from Profile where name = 'person1' and address = 'example road' and";
sql = sql.replaceAll("(?i)\\s+and$", "");
Demo

Some would simply trim the final "and" from the end of the resulting string, but it's usually better to avoid writing the final and in the first place.
If your loop looks something like this:
for (String sqlCondition : sqlConditionsList) {
sqlStatement.append(sqlCondition).append(" and ");
}
Then I'd recommend changing it to something like this:
boolean separatorNeeded = false;
for (String sqlCondition : sqlConditionsList) {
if (separatorNeede) {
sqlStatement.append(" and ");
}
sqlStatement.append(sqlCondition);
separatorNeeded = true;
}
This will only add the "and" separator when it's actually needed, between consecutive items from the list you are iterating.

You should use prepared statements or ORM. But if you still want to do that in this error-prone way, you can do it like this:
public static void main(String args[]) {
String[] params = new String[3];
params[0] = "x = y";
params[1] = "z = a";
params[2] = "b = d";
String result = String.join(" and ", params);
System.out.println(result);
}
Using join method is imho better solution than messing with trailing and.

Related

How can I ignore spaces in a substring?

I have a textbox that gives out suggestions based on user input and one of my textboxes is location based.
The problem is, if a user types in Chicago,IL, everything works, but if they type in Chicago, IL, the suggestions stop. The only difference between the two is the space after the comma.
How can I fix this, so that even if a user puts in 2 or 4 spaces after the comma it still shows the same results as the first case?
This is my code:
if (location.contains(",")) {
// the city works correctly
String city = location.substring(0, location.indexOf(","));
// state is the problem if the user puts any space after the comma
// it throws everything off
String state = location.substring(location.indexOf(",") + 1);
String myquery = "select * from zips where city ilike ? and state ilike ?";
}
I have also tried this:
String state = location.substring(location.indexOf(",".trim()) + 1);
The string variables are used to make calls to the database; that is why I have to eliminate any spaces.
How can I fix this, so that even if a user puts in 2 or 4 spaces after
the comma it still shows the same results as the first case?
you can use location.replaceAll(" ", "")
for extracting the location into city,state
you can use split() method as
String location[]=location.split(",");
Now
String city=location[0];
String state=location[1];
EDIT:(for Whome)
String location="New York, NY";
String loc[]=location.split(",");
String city=loc[0].trim();
String state=loc[1].trim();
System.out.println("City->"+city+"\nState->"+state);
you were in the right direction by using trim(). However, you put it in the wrong place.
",".trim() will always yield ",". you want to trim the result of the substring operation:
String state = location.substring(location.indexOf(",") + 1).trim();
Trim the entire result. For example:
String city = (location.substring(0, location.indexOf(","))).trim();
String state = (location.substring(location.indexOf(",") + 1)).trim();
try using java.lang.String trim() function in the correct place.
trim on ",".trim() will produce ",".
Need to trim() the final result.
if (location.contains(",")) {
String city = location.substring(0, location.indexOf(",")).trim();
String state = location.substring(location.indexOf(",")).trim();
}
Use
String state = location.substring(location.indexOf(",") + 1).trim();
Instead of
String state = location.substring(location.indexOf(",".trim()) + 1);
That should work.

How to get the specific part of a string based on condition?

I have a requirement to get the substring of a string based on a condition.
String str = "ABC::abcdefgh||XYZ::xyz";
If input is "ABC", check if it contains in str and if it presents then it should print abcdefgh.
In the same way, if input is "XYZ", then it should print xyz.
How can i achieve this with string manipulation in java?
If I've guessed the format of your String correctly, then you could split it into tokens with something like this:
String[] tokens = str.split("||");
for(String token : tokens)
{
// Cycle through each token.
String key = token.split("::")[0];
String value = token.split("::")[1];
if(key.equals(input))
{
// input being the user's typed in value.
return value;
}
}
But let's have a think for a minute. Why keep this in a String, when a HashMap is a much cleaner solution to your problem? Stick the String into a config file, and on load,
some code can perform a similar task:
Map<String, String> inputMap = new HashMap<String, String>();
String[] tokens = str.split("||");
for(String token : tokens)
{
// Cycle through each token.
String key = token.split("::")[0];
String value = token.split("::")[1];
inputMap.put(key, value);
}
Then when the user types something in, it's as easy as:
return inputMap.get(input);
The idea is that, you should split your string with the delimiters of "::" and "||" , i.e. whichever of them is encountered it will be treated as a delimiter. So, the best way for achieving that is using regular expressions, I think.
String str = "ABC::abcdefgh||XYZ::xyz";
String[] parts = str.split("[::]|[/||]");
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < parts.length - 2; i += 4) {
if (!parts[i].equals("")) {
map.put(parts[i], parts[i + 2]);
}
}
Short and concise, your code is ready. The for loop seems weird, if anyone comes up with a better regex for splitting (to get rid of the empty strings), it will become cleaner. I'm not a regex expert, so any suggestions are welcome.
Use the contains method to see if it has the sub string: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#contains%28java.lang.CharSequence%29
You could do it as follows:
String[] parts = st.split("||");
if (parts[0].startsWith("ABC")) {
String[] values = parts[0].split("::");
System.out.println(values[1]);
} else {
if (parts[1].startsWith("XYZ") {
String[] values = parts[0].split("::");
System.out.println(values[1]);
}
}
The above code will check first if ABC is there. If yes, it will print the result and then stop. If not, it will check the second section of the code to see if it starts with XYZ and then print the result. You can change it to suit your needs.

Issue in inserting string

I am having string like as follow
String first = "UPPER(substr(con.table_name,1,4)) <> 'BIN$' order by name"
String second = "and constraint_type = 'C' "
I have to insert the second string after first string of UPPER(substr(con.table_name,1,4)) <> 'BIN$'
My result
String c = "UPPER(substr(con.table_name,1,4)) <> 'BIN$' and constraint_type = 'C' order by name"
Strings are immutable so first of all you can't change the string referred to by a. You need to create a new string and reassign a to refer to the new string:
To insert the b string before the order by part in the a string, you could do
int i = a.indexOf("order by");
String newString = a.substring(0, i) + b + a.substring(i);
The result is
UPPER(substr(con.table_name,1,4)) <> 'BIN$' and constraint_type = 'C' order by name
Have a look at java.text.MessageFormat.
That allows to have a format string (like UPPER(substr(con.table_name,1,4)) <> 'BIN$' {0} order by name) formatted with parameters (your param would be and constraint_type = 'C').
If you do have control over a, one of the other answers is probably the best way to go around this.
Assuming you have no control on the contents of string a, you could call a.split("order by"), save the two resulting pieces into two variables a1 and a2 and creating a new string with b between a1 and a2. Something like this (untested):
String[] temp = a.split("order by");
String result = temp[0] + " " + b + " order by " + temp[1];
Again, I haven't really tested this, but you get the idea.
On another note, it looks like you're doing some bare sql manipulation there. Don't do this, my friend. Your code will be pretty vulnerable to sql injection. Use prepared statements instead.

SQL Query passing values from Java

I would like to know if when I place a sql query using java , does it retain the new lines?
for instance if i have
"IF EXISTS (SELECT * FROM mytable WHERE EMPLOYEEID='"+EMPID+"')"+
"UPDATE myTable SET ....)"
So after the "+" sign in the first line the UPDATE follows, does it maintain the new line when it is being passed to the database?
Thank you
No. For the query to work successfully you will have to add a space before UPDATE or after ).
Firstly, there is no newline in the example source code to "maintain" ...
Secondly, your problem is with Java rather than SQL. You will only get an newline into a Java String if you put it there explicitly; e.g.
// No newline in this string
String s = "a" +
"b";
// Line break in these strings
String s = "a" + "\n" + "b";
String s2 = "a\nb";
String s3 = "a" + System.getProperty("line.separator") + "b";
Finally, in your example, a space or TAB will do just as well as a line break.

how to parse text files, where order matters

I'm having trouble determining a way to parse a given text file.
Here is an entry in the file:
type = "book"
callnumber = "1"
authors = "a"
title = "t"
publisher = "p"
year = "2023"
each entry is separated by a line of whitespace (newline character).
so i have these variables (type, callnumber, authors, title....), and need to read this text and determine what values to set them to. For example, when i read the line "callnumber = 1", then I need set that variable to 1.
This is what I have so far. I read in a line at a time, so type = "book" for example, and then I split that line into an array of strings, with the delimiter being ", so the array would contain type = and book .
Now my problem comes in going further from there. I figured I could cycle through each string in the array, character by character, until I hit whitespace. So i would have type, but I don't have any data yet to store in type, and the grab will give me book (ignoring the = and whitespace), but how can I attribute book to type?
In summary, I'm looking for a way to parse a text file line by line, and assign variables values, based on the words I find.
Thanks.
Ignoring the current route, why not make use of Properties.load(InputStream inputStream)
Properties properties = new Properties();
properties.load(new FileInputStream("filename"));
string type = properties.getProperty("type");
System.out.println(type);
book
I agree you should take the Properties route if your requirements allow you to. The next best option would be to deal with each line individually through a regular expression.
String type = "default";
int callnumber = 0;
String line = "type = \"book\"";
// String line = "callnumber = \"1\"";
Pattern linePattern = Pattern.compile("(\\w*) = \"(.*)\"");
Matcher matcher = linePattern.matcher(line);
if ( !matcher.matches() ) {
System.err.println("Bad line");
}
String name = matcher.group(1);
String value = matcher.group(2);
if ( "type".equals(name) ) {
type = value;
} else if ( "callnumber".equals(name) ) {
callnumber = Integer.parseInt(value);
} //...
In your case you would want to integrate this into your while loop that reads from the file, and replace line with the line you've just read from the file.
To add to Aaron's solution:
Properties.load(new FileInputStream("<fileName>"));
will load the properties and to get any particular property,
use
for example,
Properties.getProperty("type")
will give you string "book".
Is the order of the variables in the text file always going to be the same?
I'm guessing you wouldn't be asking if that was the case.
Why not just make a method:
void assignVariableByName(String name, <type> value) {
if(name.contains("type"))
type = value;
else if(name.contains("callnumber"))
callnumber = value;
}
Then usage ->
You have the array of strings you split... and you call
assignVariableByName(parsedLine[0],parsedLine[1]);
Assigning values to variables has probably been done elsewhere more cleanly. If you want to 'tokenize' your string however, use a string tokenizer.
The new school is to use the split method of the String class.
token[] = line.split("\s++")
http://download.oracle.com/javase/6/docs/api/java/lang/String.html#split(java.lang.String)
Below is the old school way:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/StringTokenizer.html
While(String line = someInput.readLine())
StringTokenizer st = new StringTokenizer(line)
while(st.hasMoreTokens)
{
String token = st.nextToken()
//branch on token command, skip token '=', and assign on values
}

Categories

Resources