Retrieve database in java using JTextField to search - java

So, i would like to retrieve database information where a user will search certain columns using text fields, like this:
column1 find userinput,
column2 find userinput,
column3 find userinput,
The problem im having is the sql statement:
String sql = "select * from table where column = '" + textfield1.getText() + "'";
If textfield1 is empty, it will only retrieve entries that contain nothing.
What im trying to retrieve will have 6 text field, meaning 6 columns in the database. Using java i would need alot of if statements.
Is there any other way to shorten this?
EDIT
-- MORE INFO --
The if statements will start from:
if (!(t1.getText().equals("")) && !(t2.getText().equals("")) && !(t3.getText().equals(""))
&& !(t4.getText().equals("")) && !(t5.getText().equals("")) && (t6.getText().equals("")))
all the way down to
if (t1.getText().equals("") && t2.getText().equals("") && t3.getText().equals("")
&& t4.getText().equals("") && t5.getText().equals("") && t6.getText().equals("")
covering all possible combinations of the 6 input fields, the point of all these statements is to ignore empty text fields but provide the corresponding sql statement.
I don't know how to calculate the possible combinations other than writing them all down(i started, there was too many).

I didn't really understand why those ifs, you should elaborate more your question but i will try to help as i can.
Well, if you want to retrieve everything from the database you could use LIKE:
String sql = "select * from table where column like '%" + textfield1.getText() + "%'";
This way you'll get everything with the containing text, it means, if the field is empty it will bring all results, i guess this is the best way to do, to avoid unnecessa if clauses.
Another thing, to check for empty fields you should use:
t1.getText().trim().isEmpty()
BUT if you let they write white spaces the LIKE won't help you then you need to .trim() all your texts then your white spaces will be ignored.

The following can be formulated much neater, but to make the point:
JTextField ts = new JTextField[6];
Set<String> values = new HashSet<>(); // Removes duplicates too.
for (JTextField t : ts) {
String text = ts.getText().trim();
if (!text.isEmpty()) {
values.add(text);
}
}
// Build the WHERE condition of a PreparedStatement
String condition = "";
for (String value : values) {
condition += condition.isEmpty() ? "WHERE" : " OR";
condition += " column = ?";
}
String sql = "select * from table " + condition;
PreparedStatement stm = connection.prepareStatement(sql);
int index = 1; // SQL counts from 1
for (String value : values) {
stm.setString(index, value);
++index;
}
ResultSet rs = stm.executeQuery();
The usage of a PreparedStatement makes escaping ' (and backslash and such) no longer needed and also prevents SQL injection (see wikipedia).

i have a problem i want to search data based on multiple jtext fields where did i go wrong coz this displays only one row which has the first id
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String sql="SELECT Employee.EmpID,Employee.Fname,Employee.Mname,Employee.Sname,Employee.DoB,Employee.Phone,"
+ "Employee.Email,Employee.Nationality,Employee.Desegnition,Employee.NSSF,Employee.WCF,"
+ "Employee.BSalary,Allowance.medical,Allowance.Bonus,Allowance.others,Allowance.tov,Allowance.TA,"
+ "Attendece.Hrs from Employee,Allowance,Attendece WHERE "
+ "Employee.EmpID=Allowance.EmpID and Attendece.EmpID=Allowance.EmpID AND Employee.EmpID=? AND Attendece.Dt=?";
try{
pd=conn.prepareStatement(sql);
pd.setString(1,id.getText());
pd.setString(2,Date1.getText());
r=pd.executeQuery();
//setting the text fields
if(r.next())
{
String a=r.getString("EmpID");
eid.setText(a);
String b=r.getString("Fname");
fname.setText(b);
String c=r.getString("Mname");
mname.setText(c);
String d=r.getString("Sname");
sname.setText(d);
String e=r.getString("DoB");
dob.setText(e);
String f=r.getString("Desegnition");
Des.setText(f);
String g=r.getString("Bsalary");
bsal.setText(g);
String h=r.getString("Phone");
phone.setText(h);
String i=r.getString("Email");
email.setText(i);
String j=r.getString("Nationality");
nationality.setText(j);
String k=r.getString("Desegnition");
Des.setText(k);
String l=r.getString("NSSf");
nssf.setText(l);
String m=r.getString("WCF");
wcf.setText(m);
String n=r.getString("tov");
oh.setText(n);
String o=r.getString("Bonus");
bn.setText(o);
String p=r.getString("medical");
md.setText(p);
String q=r.getString("others");
ot.setText(q);
String s=r.getString("TA");
ta.setText(s);
String t=r.getString("Hrs");
hrs.setText(t);
int day;
day=Integer.parseInt(t)/8;
days.setText(Integer.toString(day));
double week=day/7;
weeks.setText(Double.toString(week));
}
r.close();
pd.close();
}catch(Exception e)
{
}

Related

how to make filter between two datebox zk

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 ";
}
}

How to parse a table name from CREATE statement using Hibernate?

This is a native create statement for some unknown database carrier
String createStatement = "CREATE TABLE test_database.test_table " +
"AS " +
"( " +
"var1, " +
"var2 " +
") " +
"; "
);
I need to parse this String test_database.test_table
I don't know in advance what SQL flavor this CREATE statement is. If I knew that, I would simply use something like
String table = createStatement.split(" ")[2];
But the above solution might not work in all databases. What if some database allows for blanks in table name? So I have to use Hibernate.
How?
In general, I don't think you can do this without certain assumptions or considering each and every SQL dialect you want to support.
Hibernate itself supportes a number of SQL dialects and you can infer a lot of things from the used dialect. However, org.hibernate.dialect.Dialect does not provide enough information for parse all the possible native CREATE TABLE statements in the selected dialect.
I don't think that Hibernate can take care of all situations especially when dealing with something like Transact-SQL or CREATE GLOBAL TEMPORARY TABLE or even CREATE TEMPORARY TABLESPACE and then you have the AS, AS SELECT, and even PARALLEL COMPRESS AS SELECT after the table name to consider.
As an alternative however you can create a method which can retrieve the Table Name from a supplied CREATE TABLE SQL string which I believe will cover most (if not all) of these issues. Below is such a method:
public String getTableNameFromCreate(final String sqlString) {
// Always rememeber...we're only trying to get the table
// name from the SQL String. We really don't care anything
// about the rest of the SQL string.
String tableName;
String wrkStrg = sqlString.replace("[", "").replace("]", "").trim();
// Is "CREATE TABLE" only
if (wrkStrg.startsWith("CREATE TABLE ")) {
wrkStrg = wrkStrg .substring(13).trim();
}
else if (wrkStrg.startsWith("CREATE GLOBAL TEMPORARY TABLE ")) {
wrkStrg = wrkStrg .substring(30).trim();
}
else if (wrkStrg.startsWith("CREATE TEMPORARY TABLESPACE ")) {
wrkStrg = wrkStrg .substring(28).trim();
}
// Is it Create Table ... AS, AS SELECT, PARALLEL COMPRESS AS,
// or PARALLEL COMPRESS AS SELECT?
if (wrkStrg.toUpperCase().contains(" PARALLEL COMPRESS ")) {
wrkStrg = wrkStrg.replace(" parallel compress ", " PARALLEL COMPRESS ");
tableName = wrkStrg.substring(0, wrkStrg.indexOf(" PARALLEL COMPRESS ")).trim();
}
else if (wrkStrg.toUpperCase().contains(" AS ")) {
wrkStrg = wrkStrg.replace(" as ", " AS ");
tableName = wrkStrg.substring(0, wrkStrg.indexOf(" AS ")).trim();
}
// Nope...none of that in the SQL String.
else {
tableName = wrkStrg.substring(0, wrkStrg.indexOf("(")).trim();
}
// return but remove quotes first if any...
return tableName.replace("\"","").replace("'", "");
}
If the database name is attached to the table name as in your example (test_database.test_table) then of course you will need to further parse off the actual table name.

UCanAccess data exception: numeric value out of range

I have a table called [Elenco_Aziende] from which I extract all the record in a resultset. [Elenco_Aziende] is in a relation one to many with other two tables called [Elenco_Autisti] and [Elenco_Veicoli] via a field called [Partita_IVA_Azienda] that is also primary key in [Elenco_Aziende] table.
After extracting all records from [Elenco_Aziende] I perform a loop for each value of [Partita_IVA_Azienda] and then open a new result set to try to read values in related fields of [Elenco_Autisti] and [Elenco_Veicoli] tables and do for each of them some operation.
And here comes strange thing: As long as [Partita_IVA_Azienda] (which is defined as a Text field in the Access DB) values are all the same length everything is OK when I try to read in [Elenco_Autisti] and [Elenco_Veicoli] tables, but if some of [Partita_IVA_Azienda] has a different length then I got error:
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.1 data exception: numeric value out of range
More precisely here is the nested loop scenario:
Connection con = DriverManager.getConnection("jdbc:ucanaccess://"
+ filepath);
String qry = "SELECT * FROM Elenco_Aziende";
ResultSet rs = stmt.executeQuery(qry);
String cognometest = "";
String nometest ="";
while (rs.next()) {
String partitaiva = "Partita IVA: "
+ rs.getString("Partita_IVA_Azienda") + "\n\r";
String partitaivazienda = rs.getString("Partita_IVA_Azienda");
Statement stmtautisti = con.createStatement();
System.out.println("Sto per eseguire la query per partita iva azienda = " + partitaivazienda + "\n\r");
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda="
+ partitaivazienda; /*!!!!! AND HERE WHEN I EXECUTE NEXT QUERY IS WHERE I GET THE EXCEPTION net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.1 data exception: numeric value out of range more!!!!!*/
ResultSet rsautisti = stmtautisti.executeQuery(qryautisti);
while (rsautisti.next()) {
do something here
}
Statement stmtveicoli = con.createStatement();
String qryveicoli = "SELECT * FROM Elenco_Veicoli WHERE Partita_IVA_Azienda="
+ rs.getString("Partita_IVA_Azienda");
ResultSet rsveicoli = stmtveicoli.executeQuery(qryveicoli);
while (rsveicoli.next()) {
do something else here
}
that is as soon as I execute the query
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda="+ partitaivazienda;
for a different length value of [Partita_IVA_Azienda] I get the problem.
I even tried to export the database in a comma separated value and reimporting it in a brand new one but it did not help. Furthermore, the problem seems to happen just for large number of records in tables [Elenco_Autisti] (138 records) and [Elenco_Veicoli] (287 records), while seems not to happen for small number of records. [Elenco_Aziende] is small (no more than 10 records).
According to the little of what I know about SQL, a WHERE with a text field should be written with the value in apostrophes:
String qryautisti = "SELECT * FROM Elenco_Autisti WHERE Partita_IVA_Azienda='"
+ partitaivazienda + "'";

Check if number is already in field before concatenating?

I am writing a crawler that scans many urls and then puts all the words found in each webpage into a table. In this same table the ID of the url is stored. If the word is repeated in another page, the ID of the url the word was found on is concatenated with a comma separating them. So if a word appears on multiple pages, all the concatenated ID numbers in the field might look like:
2,3,6,8,9
At the moment, if the number appears multiple times on the same page, the ID number will be added each time the number is found so the URLID field might end up looking like:
2,2,2,4,7,8,8,8,8,8,9,9
Using Java is there a way I get it to check if the number exists in the field already and only add it if it is not already there? I have looked through the api but cannot seem to find a suitable way to do this. Any ideas?
Addition:
public void updateWordTable( String[] array, int urlid ) throws SQLException, IOException {
Statement stat = connection.createStatement();
String wordQuery;
String query;
for (String item : array) {
if(item.matches("[A-Za-z0-9]+")){
wordQuery = "SELECT * FROM word WHERE word = '"+item+"'";
ResultSet rs = stat.executeQuery(wordQuery);
if(!rs.next()){
query = "INSERT INTO word VALUES ('"+item+"',"+urlid+")";
stat.executeUpdate( query );
}
else {
//query = "UPDATE word SET urlid = concat(urlid, ',"+urlid+"') WHERE word = '"+item+"' ";
//query = "UPDATE word SET urlid = CASE WHEN FIND_IN_SET( '"+urlid+"', urlid ) > 0 THEN urlid ELSE CONCAT( urlid, ',', '"+urlid+"' )END WHERE word = '"+item+"' ";
String query2 = "UPDATE word SET urlid = CASE WHEN FIND_IN_SET( ?, urlid ) > 0 THEN urlid ELSE CONCAT( urlid, ',', ? )END WHERE word = ? ";
PreparedStatement pst = connection.prepareStatement( query2 );
pst.setLong( 1, urlid );
pst.setLong( 2, urlid );
pst.setString( 3, item);
int result = pst.executeUpdate();
//stat.executeUpdate( query2 );
}
}
}
stat.close();
}
... is there a way I get it to check if the number exists in the field already and only add it if it is not already there?
You can do it using JAVA, but leave that checking to MySQL as it has such search features.
Using MySQL, you can use FIND_IN_SET function on comma separated values in the column. This will solve your problem to not reprocess in JAVA to find if such id exists.
select
FIND_IN_SET( value_to_find, column_with_cs_values ) > 0 as bool_matched
from table_name
Add where condition and others if any required.
And in the JAVA code you can just read the resultset for getBoolean.
boolean idMatched = rs.getBoolean( "bool_matched" );
if( idMatched ) {
// dont update table
}
else {
// update table
}
Alternatively, you can directly update the table column.
Example:
UPDATE table_name
SET column_name_with_cs_values =
CASE WHEN FIND_IN_SET( value_to_find,
column_name_with_cs_values
) > 0 THEN column_name_with_cs_values
ELSE CONCAT( column_name_with_cs_values, ',', value_to_find )
END
-- add where etc here
;
In JAVA, you can use the above query like the following with PreparedStatement.
String query = "UPDATE word
SET urlid = CASE WHEN FIND_IN_SET( ?, urlid ) > 0 THEN urlid
ELSE CONCAT( urlid, ',', ? )
END
WHERE word = ? ";
PreparedStatement pst = con.prepareStatement( query );
pst.setString( 1, urlid );
pst.setString( 2, urlid );
pst.setString( 3, item);
int result = pst.executeUpdate();
I guess your values are stored in mysql because your question is tagged mysql. In java you can request your database with a select and check if the value is already inserted.
Or if your are not in the mysql world but only java, use a structure that give you the guartantee of unicity as a Set instead of a List.
The easiest way would be just to load those values into Set. Set will take case to have unique elements only.
The idea is whenever you store your IDs this structure should keep uniqueness. Set is the best one when we talk about Java.
If you would like to have some mechanism on database to provide uniqueness that's another story.
That's just the general tip.
If your field is a String then you can use regex
boolean exists = s.matches("(^|.*,)"+ n + "($|,.*)");
Step1: Store new url_id in temp variable.
Step2: now check this url_id existence in your table by select statement, you can do this by below query, suppose new url_id is 7:
SELECT COUNT(url_id) FROM mytable WHERE (url_id LIKE '7,%' OR url_id LIKE '%,7' OR url_id LIKE '%,7,%');
Step3: if you get any count from above query then leave it, otherwise add in your table.
I was having a project coded in pl/sql that comes across the case like yours. My variable is stored in a String and I have to check if the number was already in the String variable. I did it from using
IF instr('2,3,6,8,9,' '2,') <= 0 THEN
' Code to append the '2,'
End If
For JAVA there is something similar to instr method, String.indexOf()
http://www.tutorialspoint.com/java/java_string_indexof.htm
However note that it will return 0 if it's the first character, so probably it will be < 0
String a = "2,3,6,8,9,";
If a.indexOf(ID + ",") < 0 { // -1 equivalent to NOT FOUND
// code to append ID + ",";
}
Note I need to check on ID + "," reason is e.g.
ID = "2";
a = "20,3,6,8,9,";
It will return me 0 due to the 20. Therefore I'm using comma as a delimiter for every number found.
So after I finish append variable a, I would remove the last comma by
a = a.substring(0, a.length()-1); // this will remove the last ","
System.out.println(a); // the output should be - 2,3,6,8,9
This is using Java if your variable is stored in Java.

Error: Before start of result set in Java

I know this would be a foolish question to ask but still i need to do this.
This is a basic program in java application where I want to use 3 queries simultaneously to print the table.
(I'm not using any Primary key in this case so please help me to resolve this without making my attributes as primary keys - I know this is not a good practice but for now i need to complete it.)
my code:
Connection con = null;
Statement stat1 = null, stat2 = null, stat3 = null;
ResultSet rs1, rs2, rs3;
stat1 = con.createStatement();
stat2 = con.createStatement();
stat3 = con.createStatement();
String str = "\nProduct\tC.P\tS.P.\tStock\tExpenditure\tSales";
info.setText(str);
String s1 = "SELECT type, cp, sp, stock FROM ts_items GROUP BY type ORDER BY type";
String s2 = "SELECT expenditure FROM ts_expenditure GROUP BY type ORDER BY type";
String s3 = "SELECT sales FROM ts_sales GROUP BY type ORDER BY type";
rs1 = stat1.executeQuery(s1);
rs2 = stat2.executeQuery(s2);
rs3 = stat3.executeQuery(s3);
String type;
int cp, sp, stock, expenditure, sales;
while( rs1.next() || rs2.next() || rs3.next() )
{
type = rs1.getString("type");
cp = rs1.getInt("cp");
sp = rs1.getInt("sp");
stock = rs1.getInt("stock");
expenditure = rs2.getInt("expenditure");
sales = rs3.getInt("sales");
info.append("\n" + type + "\t" + cp + "\t" + sp + "\t" + stock + "\t" + expenditure + "\t" + sales);
}
Output:
Runtime Exception: Before start of result set
This is the problem:
while( rs1.next() || rs2.next() || rs3.next() )
If rs1.next() returns true, rs2.next() and rs3.next() won't be called due to short-circuiting. So rs2 and rs3 will both be before the first row. And if rs1.next() returns false, then you couldn't read from that anyway...
I suspect you actually want:
while (rs1.next() && rs2.next() && rs3.next())
After all, you only want to keep going while all three result sets have more information, right?
It's not clear why you're not doing an appropriate join, to be honest. That would make a lot more sense to me... Then you wouldn't be trying to use multiple result sets on a single connection, and you wouldn't be relying on there being the exact same type values in all the different tables.
You do an OR so imagine only one ResultSet has a result.
What you end up with is trying to read from empty result sets.
Suppose rs1 has one result and rs3 has 3 results. Now as per your code it will fail for rs1.getString("type"); during second iteration.
Better to loop over each resultSet separately.
This is going to go badly wrong, in the event that there is a type value that's missing from one of your three tables. Your code just assumes you'll get all of the types from all of the tables. It may be the case for your current data set, but it means that your code is not at all robust.
I would seriously recommend having just one SQL statement, that has each of your three selects as subselects, then joins them all together. Your java can just iterate over the result from this one SQL statement.

Categories