This question already has answers here:
How does a PreparedStatement avoid or prevent SQL injection?
(10 answers)
Closed 7 years ago.
I am trying to make a to-do list using NetBeans-8.0.2 and JavaFX (FXMLApplication) that stores memory into MySQL database.
I know that, SQL query takes inverted comma -> ( ' ) and
double quotation -> ( " ) as the same to understand a string.
Now, what i am trying is, (today is my sister's birthday) i am trying to add a task in my list that says: It's Rahi's birthday!
but, due to sql query, it is failing.
it's because inside the code, input's inverted comma is making a complexity in the sql query as a whole.
#FXML
private void handleAddTaskAction(ActionEvent event) {
String date = addTaskDatePicker.getValue().toString();
System.out.println(date);
String hour = hourComboBox.getValue() + "";
String minute = minuteComboBox.getValue() + "";
String where = whereField.getText();
String header = headerField.getText();
String description = descriptionArea.getText();
if(hour.length()==0)
hour= "12 AM";
if(minute.length()==0)
minute= "00";
if(header.length()==0)
header= "(No header available)";
if(description.length()==0)
description= "(No description available)";
if(header.length()==0 && description.length()==0){
header= "(Empty task)";
description= "(Empty description)";
}
String query = "insert into task values('" + date + "','" + hour + " " + minute + " minutes', '"
+ header + "', '" + description + "', 'at " + where + "');";
if (date.length() >= 1) {
try {
statement.execute(query);
} catch (SQLException ex) {
//Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Error occured!");
alert.showAndWait();
}
} else {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setHeaderText("You must select a date.");
alert.showAndWait();
}
}
i want to store the message as it is typed. Any solutions ?
my database table description and The GUI are attached as picture.
Ask me if you need anything else.
Thank you.
Picture of: GUI and
Picture of: Table description
Just use a PreparedStatement to inject your values, it will escape them for you.
Related
I am having trouble with altering the search parameters within SQLite, currently, the search functions that I have for searching film titles and genres can only return the specific result, e.g., Action will only bring back Action films and not Action, Adventure films.
I have had a friend manage to have it work within the SQLite Studio itself, but using this method has been unsuccessful. He suggested using the following ORDER BY, however, it still gives the same results.
Cursor c = sqdb.rawQuery("SELECT * FROM filmography WHERE genre LIKE '%" + searchGenre + "' ORDER BY LENGTH(genre) ASC",
null);
I am at a loss now as I cannot seem to come across or figure out the answer. How would I go about changing the SQL so that if you were to search say "Action" in the genre search, it would bring back all results so eg., "Film 1 = Action, Film 2 = Action, Adventure, Film 3 = Action, Crime" and so on?
Example of genre data: "Capone, Biography, Crime, Drama, Fonse, 2020, 4.7/10
Black Hawk Down, Drama, History, War, Twombly, 2001, 7.7/10
Venom, Action, Adventure, Sci-Fi, Eddie Brock / Venom, 2018, 6.7/10
public String searchByTitleInFilmography(SQLiteDatabase sqdb, String searchfilmTitle)
{
String result = "";
Cursor c = sqdb.rawQuery("SELECT * FROM filmography WHERE filmTitle = '" + searchfilmTitle + "'",
null);
if (c != null)
{
if (c.moveToFirst())
{
do
{
String id = c.getString(0);
result = result + id + ": ";
String filmtitle = c.getString(1);
result = result + "Title: " + filmtitle + ". ";
String genre = c.getString(2);
result = result + "Genre(s): " + genre + ". ";
String role = c.getString(3);
result = result + "Role: " + role + ". ";
String year = c.getString(4);
result = result + "Released: " + year + ". ";
String imdbrating = c.getString(5);
result = result + "Rating: " + imdbrating + "\n" + "\n";
Log.w("FILM_TITLE_GENRE", "ID - " + id +":" + " Genre(s) = " + genre);
} while (c.moveToNext());
}
else
{
result = "No Films Found With The Title = " + searchfilmTitle;
}
}
c.close();
return result;
} // public String serachByTitleInFilmography(SQLiteDatabase sqdb, String searchTitle)
If the column genre contains values like a comma separated list of genres, then you should change the operand of the operator LIKE like this:
String sql = "SELECT * FROM filmography WHERE ',' || REPLACE(genre, ', ', ',') || ',' LIKE '%,' || ? || ',%'"
Cursor c = sqdb.rawQuery(sql, new String[] {searchGenre});
REPLACE() removes all spaces after each comma and each value of genre becomes like: ',Action,Crime,Drama,'.
When you pass 'Action' as the parameter for the ? placeholder then the sql statement becomes:
SELECT * FROM filmography WHERE ',Action,Crime,Drama,' LIKE '%,Action,%'
which is what you want: all the rows that contain 'Action' anywhere in the column genre.
I have a list of objects provided by another service which I use to update my own data. When I try to use NamedParameterJdbcTemplate.batchUpdate, all returned values are zero.
public void updateWeather(List<Weather> weatherList) {
String query = "UPDATE weather \n" +
"SET rain_probability = ROUND(:rainProbability, 4), \n" +
"wind_speed = :windSpeed \n" +
"WHERE city_id = :cityId AND date = :date;";
List<MapSqlParameterSource> batchList = new ArrayList<>();
for(Weather weather : weatherList) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("rainProbability", weather.getRainProbability());
params.addValue("windSpeed", weather.getWindSpeed());
params.addValue("cityId", weather.getCityId());
params.addValue("date", weather.getDate());
batchList.add(params);
}
this.namedParameterJdbcParameter
.batchUpdate(query, batchList.toArray(new MapSqlParameterSource[] {});
}
If I run this UPDATE directly in the database, it works fine. Futhermore, if I run it one by one, that is, replacing values (instead of adding the parameter source to batchList) it also works.
For example:
for (Weather weather : weatherList) {
String query = String.format("UPDATE weather \n" +
"SET rain_probability = ROUND('%d', 4), \n" +
" wind_speed = %d \n" +
" WHERE city_id = :cityId AND date = :date;",
weather.getRainProbability(),
weather.getWindSpeed(),
weather.getCityId(),
weather.getDate()
);
this.namedParameterJdbcTemplate.update(query, Collections.emptyMap());
}
Any suggestions of what I'm doing wrong?
Is it the use of "\n" or the ";" at the end of the statement within the String? (I'm surprised you don't get a SQL Syntax exception with the ; inside the actual query string)
Also dates are always a bit tricky and if that isn't converting properly then your WHERE clause isn't going to match and is possibly why 0 rows are returned. Could you temporarily try converting dates to Strings and see if the count is correct (e.g. for Oracle: AND date = TO_DATE(:dateStr, 'DD/MM/YYYY') )
(Edit: This is a question that I had and I answer it in the hopes of helping someone else who had a similar question.)
I am trying to clean up geographic data in my Google Fusion Table and would like to write a Java program to read in select Fusion Table rows, modify columns in each row and write out the modified rows back to the original fusion table.
I have found Christian Junk's example code in the Google API Client Libraries documentation: "fusiontables-cmdline-sample" that shows how to: Authorize access to a users fusion tables, list tables, create a table, insert data into a table, show rows, delete a table.
How do I modify this example to make updates to selected rows in a table? (see answer with code below)
[edit]: I didn't find any good solutions on the Net. I have written the solution in Java and will answer in the answers in the hope that it can help someone else how is trying to do this. I am a novice Java programmer so the code reflects that. I also needed to get nearby big cities based on a gps location and used GeoNames api (citiesJSON) creating a bounding box to do that. This solution uses JSON to access items returned from REST calls.
I have written a Java program that does the row data modification described in the question. It uses Christian Junk's example noted in the question and also calls GeoNames citiesJSON webservice as described in the question (sending bounding box coordinates in the parameters). I'm a novice in Java so the code is what it is. I do a lot of commenting in order to reuse code, like SQL queries, later.
You can find my solution on Github at: FusionTableModifyJava
The primary module of interest is: FusionTableSample.java
Here are the functions that do the getRows and updateRows. Everything else can be seen at github (by Microsoft$):
private static void getRows(String tableId) throws IOException {
View.header("Updating Rows From Table");
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number FROM " + tableId +
" Where Manager = '' AND 'Review 1' CONTAINS IGNORING CASE '.fs.' Order by Number ASC LIMIT 3000");*/
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number FROM " + tableId +
" Where 'Area Name' CONTAINS IGNORING CASE 'Tioga George' Order by Number ASC LIMIT 3000");*/
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number FROM " + tableId +
" Where 'Area Name' ='' Order by Number DESC LIMIT 2000");*/
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number FROM " + tableId +
" Where 'Area Name' CONTAINS 'X01' Order by Number DESC LIMIT 1"); */
/*AND 'City (nearest)' DOES NOT CONTAIN IGNORING CASE 'Mexico'*/
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number, Location FROM " + tableId +
" Where State = '' Order by Number DESC LIMIT 100");*/
/*Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number, Location FROM " + tableId +
" Where State = 'BCS' Order by Number DESC LIMIT 100");*/
Sql sql = fusiontables.query().sql("SELECT RowID, 'Area Name', Notes, Number, Location, State, Codes FROM " + tableId +
" Where State = 'ID' AND 'City (nearest)' = '' Order by Number DESC LIMIT 100");
try {
Sqlresponse response = sql.execute();
// System.out.println(response.toPrettyString());
mylist = response.getRows();
} catch (IllegalArgumentException e) {
// For google-api-services-fusiontables-v1-rev1-1.7.2-beta this exception will always
// been thrown.
// Please see issue 545: JSON response could not be deserialized to Sqlresponse.class
// http://code.google.com/p/google-api-java-client/issues/detail?id=545
}
}
private static void updateRows(String tableId) throws IOException {
// IOException needed ParseException
count = 1;
mylist.forEach((myRow) -> {
try {
// modify fields in table...
//newAreaName = kt.firstpart(myRow.get(NOTES).toString()); //get Notes first sentence
//newAreaName = newAreaName.replace("'", "''");
//newAreaName += " X01";
//String state = getStateFrmLoc(myRow.get(LOCATION).toString());
//String state = "MX-BCS";
float km;
if ( "AK,MT,NV".contains(myRow.get(STATE).toString()) ) {
km = 180f; // 111.85 miles
} else {
km = 80.5f; // 50 miles
}
BigCity big = new BigCity(myRow.get(LOCATION).toString(), km);
String cityState = big.cityName +", "+big.state;
if (big.population < 10000f) {
System.out.println("Skip for low population :"+myRow.get(NUMBER));
} else {
sqlupdate = "UPDATE " + tableId + " " +
"SET 'City (nearest)' = '" + cityState + "' " +
",'Codes' = '" + myRow.get(CODES).toString() + ",#U1' " +
"WHERE ROWID = " + myRow.get(ROW_ID);
System.out.println("[" + count + "]" + myRow.get(NUMBER) + ": " + sqlupdate);
// do the update...
if (!mtest) { // if testing then don't update
sql_doupdate(sqlupdate);
}
count++;
if ((count % 30) == 0) {
System.out.println("waiting 60 seconds");
TimeUnit.SECONDS.sleep(60); //Fusion Tables allows 30 updates then must wait 1 minute.
}
}
} catch(Exception e){
System.out.println(e.getMessage());
}
});
}
I have 2 datebox to make a filter. Their value will determine the 'from' and 'to' in my query (I'm using Oracle now), here is the code.
#Listen("onClick=#btnSaveFilter")
public void saveFilter() throws Exception {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
c_main_filter.detach();
cc.refreshFilter(""
+"[Date of Birth] between '" + formatter.format(dbDateBirthFrom.getValue()).toString() + "' "
+ "and '" + formatter.format(dbDateBirthto.getValue()).toString() + "'");
}
when both datebox has value, the query work. but when they have no value the query is giving no data.
when datebox has value, it's giving data
"[Registration Date] between '2010-09-23' and '2010-09-23' "
when datebox has no value, it's giving no data
"[Registration Date] between '' and '' "
like another filter I expect if the value is '' then all data will appear, but not :D hahaha. the condition is more than this actually, the filter has a lot of parameter one of them is this condition, and some of them use date format so there will be more condition like this.
do you know how to elegantly fix this problem, I've been thinking to use 'if' to determine the datebox has value or no then I will append the text to query text if both of them has value, but then I found another problem how I can add 'and' in query to give another condition,
let say I have 5 conditions so then
"select * from xxxx where 1stcondition and 2ndcondition and
3rdcondition and 4thcondition and 5th condition"
so when the dateboxes of the 5thcondition has no value the query will be wrong like this
"select * from xxxx where 1stcondition and 2ndcondition and
3rdcondition and 4thcondition and"
if I want to use 'if' how can I play with the 'and'? but if you have alternative it will be great cause I don't have to deal with 'if' :D
You can use String.isEmpty() to determine whether you need to put an and:
String where = "";
if (from != null && to != null) {
where += <yourDateCondition>;
}
if (<needToAddSecondCondtion>) {
if (!where.isEmpty()) {
where += " and ";
}
where += <secondCondition>;
}
// continue with other conditions
String query = "select * from xxxx where " + where;
I don't know if you use plain JDBC or ORM framework like hibernate to querying to the database, but you can try something like this :
public void saveFileter(){
StringBuilder sb = new StringBuilder();
sb.append("select * from table ");
if(dbDateBirthFrom.getValue() != null{
sb.append(determineFilterWord(sb.toString()));
sb.append("your condition ");
}
if(dbDateBirthTo.getValue() != null{
sb.append(determineFilterWord(sb.toString()));
sb.append("your condition ")
}
session.createQuery(sb.toString()); //if you using hibernate
}
private string determineFilterWord(String query){
if(query.toLowerCase().indexOf("where") != -1){
return "and ";
}else{
return "where ";
}
}
I can't find a way of putting all the selected items on 3 different combobox which I need to insert as query to Java DB(derby). Here's my code.
int response = JOptionPane.showConfirmDialog
(null, "Do you want to add the employee?","Confirm",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
if(response == JOptionPane.YES_OPTION){
try{
String url="jdbc:derby://localhost:1527/EMPLOYEEINFO [ADMIN1 on ADMIN1]";
String username="ADMIN1";
String password="ADMIN1";
Connection con = DriverManager.getConnection(url, username, password);
Statement stat = con.createStatement();
String Query =
"INSERT INTO EMPLOYEE (EMPLOYEE_ID,EMP_LASTNAME,EMP_FIRSTNAME,EMP_MIDDLENAME,ADDRESS,POSITION ) "
+"VALUES "
+ "(' "+AddEmployee_EmployeeID_TxtField.getText()+" ',"
+ " ' "+AddEmployee_LastName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_FirstName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_MiddleName_TxtField.getText()+" ',"
+ " ' "+AddEmployee_Address_TxtField.getText()+" '"
+ " ' "+AddEmployee_Position_TxtField.getText()+" ',"
+ " ' "+AddEmployee_Gender_ComboBox.getSelectedItem()+"')"
;
stat.execute(Query);
JOptionPane.showMessageDialog(null,"Insert Success!");
And below is the screenshot. I'm thinking of getselectedObject but i have 3 combo boxes so I really don't know how. Please help.
I need to get the selected items of Month, Day and Year of the Birthday then insert it to my table in Derby. Thanks in advance.
You should create a separate method to get the fields and combine the values into a formatted date. Something like this:
private String getDateFromFields() {
String month = monthComboBox.getSelectedItem();
String day = dayComboBox.getSelectedItem();
String year = yearComboBox.getSelectedItem();
// Format this the way your database expects.
String formattedDate = month + "/" + day + "/" + year;
}
You just call this method and you will get back the formatted date string that you can use in your query. Change the variable names of the combo box fields to match your names and format the string into what your database expects and you should be good to go!
You can do something like this:
String bDay=dayCombo.getSelectedItem()+"-"+monthCombo.getSelectedItem()+"-"+yearCombo.getSelectedItem();
But I will recommend you to use JDatechooser in this case.
JDateChooser bDayChooser =new JDateChooser();
bDayChooser.setDateFormatString("dd-MM-yyyy");//format visible date of the date chooser as you need
String bDay=((JTextField) bDayChooser.getDateEditor().getUiComponent()).
getText();