Multiselect month from table - sqlite - java

I get 1-n selected months from a JList.
Now I'd like to select rows from a sqlite DB with the selected months.
Is there a way to do it the easy way to build the select string, e.g. with a loop and a LIKE statement?
resultSet = statement
.executeQuery("SELECT sum(Betrag) FROM record WHERE strftime('%Y',Datum)='"
+ options.getList_years().get(options.getCurrent_year_index())
+ "' AND strftime('%m',Datum) LIKE '"
+ "02 || 04 || 12" //Here are the months,
+ "' AND Sektion LIKE '"
+ "%"
+ "' AND Inhaber LIKE '"
+ list_accounts.getSelectedValue()
+ "' AND Ausgabe='"
+ "true';");
Or has it to look that way?
strftime('%m',Datum)='02' OR strftime('%m',Datum)='04' OR trftime('%m',Datum)='12'

You should use an IN clause:
... AND strftime('%m',Datum) IN ('02', '04', '12')
But you should definitely not use string concatenation to set parameters dynamically in your query. This is the best way to suffer from SQL injection attacks. Use prepared statements, with a ? placeholder for each of your parameter:
SELECT sum(Betrag) FROM record WHERE strftime('%Y',Datum) = ? ...
Learn more about prepared statements in the JDBC tutorial.
You will indeed have to use some loop or utility to build the IN clause. StringUtils from commons-lang is useful here:
"... AND strftime('%m',Datum) IN (" + StringUtils.repeat("?", ", ", months.size())

Related

JPQL Create "Dynamic" Query to execute in repository

Edit-
I'll add the use case to clear up the function of this.
The user will select two dates - a start date and an end date - these are then passed on and used to select the tables (each year has its own table). In one use case where the two given dates lie in the same year it's a simple query on that table alone.
However, if the two dates are different years I will need to join all tables (so 2011-2013 will be three tables connected, to search through) and thus, I want a dynamic fix to this. I know building up a query like below is against security - just thought something similar would work. As the system will get new tables each year I also dont want to have to manually add however many new queries for each case (2011-2016, 2014-2018, 2011-2019.. etc)
I have a question about whether it is possible to create a dynamic query as a String like below and then pass that through to service -> repository, and use that as a query?
for (int i = 0; i < yearCondition; i++) {
if (i == 0) {
query += "SELECT md.Device_ID, l.locationRef, " + reportRunForm.getStartDate() + " as 'From Date', "
+ reportRunForm.getEndDate() + " as 'To Date' "
+ "from mData.meterdata" + iDateStart.substring(0, 4)
+ " join MOL2.meters m on device_ID = m.meterUI "
+ "join MOL2.locations l on m.locationID = l.locationID "
+ "join MOL2.meterreg mr on m.meterID = mr.meterID "
+ "where mr.userID = ?1";
}
query += "UNION SELECT md.Device_ID, l.locationRef, " + reportRunForm.getStartDate() + " as 'From Date', "
+ reportRunForm.getEndDate() + " as 'To Date' "
+ "from mData.meterdata" + (Integer.parseInt(iDateStart.substring(0, 4))+i)
+ " join MOL2.meters m on device_ID = m.meterUI "
+ "join MOL2.locations l on m.locationID = l.locationID "
+ "join MOL2.meterreg mr on m.meterID = mr.meterID "
+ "where mr.userID = ?1";
}
I may have the wrong idea with how this works, and I know I could create and persist a query through entitymanager, but wanted to know whether doing it through the repository would be possible?
My thought was I'd build up the query like above, pass it through to service and then to repository, and bind it as value in #Query annotation but this doesn't seem possible. I'm likely approaching this wrong so any advice would be appreciated.
Thanks.
Edit -
Had a goof. Understand doing it at all like that is stupid, an approach to build up something similar is what I'm looking for that is still secure.
Maybe this annotations before your POJO can help
#org.hibernate.annotations.Entity(dynamicInsert = true)
for example two tables district and constituency ...
Dynamic query
query += "select *from constituency c where 1=1";
if(constituencyNumber!=null)
query +=" and c.constituency_number like '"+constituencyNumber+"%'";
query += " group by c.district_id";
OR
select *from constituency c where (c.constituency_number is null or c.constituency_number like '1%') group by c.district_id;

Pass email as a parameter for SQL query, PostreSQL, JAVA

I'm trying to pass the email as a parameter for the SELECT SQL query in my JAVA back-end.
As i understood, for some reason it pass only "email_name" from the "email_name#email.com". (Getting this error):
Threw a SQLException creating the list of blogs.
ERROR: column "email_name" does not exist
Position: 174
There is an existed rows, which contains "email_name#email.com".
(Why "ERROR: column"? according to query it should look for a value, no?)
Here is My query:
String active_user = "email_name#email.com"; //email_name#email.com - example, active_user receive some path variable and on this particular moment(before query execution) contains exactly "email_name#email.com".
ResultSet rs = st.executeQuery("SELECT \n" +
" goods.item_title, \n" +
" goods.item_descr, \n" +
" goods.item_email,\n" +
" goods.item_images,\n" +
" goods.item_phone, \n" +
" goods.item_price \n" +
"FROM \n" +
" public.goods\n" +
"WHERE goods.owner = "+active_user+"\n" +
"ORDER BY\n" +
" goods.item_id ASC;");
So the question is - how to pass full email to query?
Try using String active_user = "'email_name#email.com'";. with single quotes. Since postgre recognized as column when you use double quotes.
You should use PreparedStatement. this is a example
Very unsafe approach, you should use PreparedStatement to avoid SQL injection. Here is existing answer

How do I form this complex query in Hibernate?

I'm building a REST service using Hibernate, Spring HATEOAS and Jackson. I am adding a method which returns a JSON representation of the results of a query like the one below;
SELECT ERRORS.DMN_NAM, CODES.MSG_TXT,
FROM SERV_ERR ERRORS, EVENT_CD CODES
WHERE ERRORS.SERV_RESP_CD_TXT = CODES.CD_TXT
GROUP BY ERRORS.DMN_NAM, ERRORS.SERV_NAM, CODES.MSG_TXT,
ERRORS.SERV_ERR_CNT, ERRORS.ERR_TS_NUM
ORDER BY ERRORS.DMN_NAM, CODES.MSG_TXT
I currently have two objects defined (ErrorsEntity and EventCodeEntity) which map to the tables SERV_ERR and EVENT_CD.
So the results of this query will be a list, but not of ErrorsEntity or EventCodeEntity but rather an amalgamation of the two entities.
Up to now, my queries have all returned objects that map directly to one table like so:
public List<ErrorsEntity> getErrors(double daysPrevious, double hoursToShow);
What's the best way to handle this in Hibernate where the results of a query aren't objects that are mapped to a single table and how can I write this query in HQL?
It's better to stick to an SQL query then, since HQL makes sense only when you plan on changing states from the resulted entities. In your case, the SQL is a better alternative, since it doesn't really follow the standard and you only want a projection anyway. You could remove the group by with distinct but it will require a derived table, which can be done in plain SQL anyway.
List dtos = s.createSQLQuery(
"SELECT " +
" ERRORS.DMN_NAM AS dmnNam, " +
" CODES.MSG_TXT AS msgTxt " +
"FROM SERV_ERR ERRORS, EVENT_CD CODES " +
"WHERE ERRORS.SERV_RESP_CD_TXT = CODES.CD_TXT " +
"GROUP BY " +
" ERRORS.DMN_NAM, " +
" ERRORS.SERV_NAM, " +
" CODES.MSG_TXT, " +
" ERRORS.SERV_ERR_CNT, " +
" ERRORS.ERR_TS_NUM " +
"ORDER BY " +
" ERRORS.DMN_NAM, " +
" CODES.MSG_TXT "
.addScalar("dmnNam")
.addScalar("msgTxt")
.setResultTransformer( Transformers.aliasToBean(MyDTO.class))
.list();
Make sure YourDTO has a matching constructor, and the types are the exactly like ee.dmn.nam and ece msgTxt.
Instead of group by I'd choose:
SELECT dmnNam, msgTxt
FROM (
SELECT DISTINCT
ERRORS.DMN_NAM AS dmnNam,
ERRORS.SERV_NAM,
CODES.MSG_TXT AS msgTxt,
ERRORS.SERV_ERR_CNT,
ERRORS.ERR_TS_NUM
FROM SERV_ERR ERRORS, EVENT_CD CODES
WHERE ERRORS.SERV_RESP_CD_TXT = CODES.CD_TXT
ORDER BY
dmnNam,
msgTxt
) as DATA

java.sql.SQLSyntaxErrorException: ORA-00936: missing expression

I wrote a simple SQL query in Oracle which inserts some values.
But I got SQLSyntaxErrorException stating a "missing expression" error.
This my query:
String addManager = "INSERT INTO property_manager(EIN,NAME,HOME_PHONENUMBER,MOBILE_PHONENUMBER,EMAIL,PROPERTY_CIN)" +
"VALUES (" + mein.getText() + "," + mname.getText() +","+ mHome_phonenumber.getText() +","+ MMobile_phonenumber.getText()+"," + memail.getText() + ","+mproperty_cin.getText()+")";
The best solution is using a java.sql.PreparedStatement.
It prevents SQL injection
Escapes invalid characters in your Strings (such as ') and the characters which will break your query
handles null and empty Strings
Uses Oracle's query parsing cache (for better performance)
Handles types such as Date and Blob much easier
Just google for java PreparedStatemnt and you see lots of samples.
You should put your values inside quotes.
String addManager = "INSERT INTO property_manager(EIN,NAME,HOME_PHONENUMBER,MOBILE_PHONENUMBER,EMAIL,PROPERTY_CIN)" +
"VALUES ('" + mein.getText() + "','" + mname.getText() +"','"+ mHome_phonenumber.getText() +"','"+ MMobile_phonenumber.getText()+"','" + memail.getText() + "','"+mproperty_cin.getText()+"')";
Or better yet, use parameters. Otherwise you risk sql injection attack.

Writing to access database in Java?

I'm working on a database project about adding, editing and deleting registries to a Students table which has fields:
Last_names, Names, IcNumber, Average, Entry_mode, Career and Change
In the editing frame i have a field where user types the icnumber of the student to edit its data, asks for the new data and saves it to a "Students" data structure, and then reupdates the registry with the new data:
String stmnt = "Insert Into Students (Last_names, Names, IcNumber, Average, " +
"Entry_mode, Career, Change) Values ('" + student.getLastNames() +
"', '" + student.getNames() + "', '" + student.getIcNumber() + "', " +
student.getAverage() + ", '" + student.getEntry() + "', '" +
student.getCareer() + "', '" + student.getChange() + "') " +
"Where IcNumber = '" + field.getText() + "'";
statement.execute(stmnt);
And i get this Error message:
[Microsoft][Microsoft Access ODBC Driver] "Query input must contain at least one table or query."
I have tried a similar SQL Instruction in the adding registry area of my program without the "Where" condition and works good, anyone knows about that error?
You should use a subquery, first the SELECT part with WHERE and then the INSERT part
Something like:
if (cond){
(SELECT.....)
(INSERT INTO...)}
Why are you using where in a insert statement? Where clause is applicable in select, update and delete statements but not in insert. Also I don't see any need of the where clause in your query.
Simply use the insert statement without where clause.
Use an INSERT statement to add a new record. A WHERE clause does not belong in an INSERT statement.
If you're editing an existing record, then you should use an UPDATE statement, and a WHERE clause makes sense to identify which record to change.

Categories