How do I retrieve data from multiple tables (PostgreSQL) in Java Servlet? - java

I having difficulties on retrieving data from multiple tables. It is going to be a search form and its a relational database.
Question1: How do I retrieve data from multiple tables now?
Question2: At the same time another problem I face is that I can not get any results if I try to search only by Name or Lastname. I get results only when I use date of birth. Why?
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
java.io.PrintWriter out = response.getWriter();
Connection conn = null;{ // while there is no connections, proceed to the next step
try {
Class.forName("org.postgresql.Driver"); // importing the driver to use the getConnection method
conn = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/caglar", "postgres", //?searchpath=cag
"abracadabra");
System.out.println("Connected to the database"); // console message
String agent_name = request.getParameter("givenname"); // variable - reads from user input
String agent_lastname = request.getParameter("familyname"); // variable - reads from user input
String dob = request.getParameter("birthyear"); // variable - reads from user input
ArrayList al=null;
ArrayList agent_list =new ArrayList();
//Problem 1: If dob is not given, it is not searching by name or lastname.
//String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' or birthyear='"+dob+"' order by givenname";
String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' ";
if(dob!=null && !"".equals(dob)) // if date of birth fiel is left blank, it will still proceed to the results page
query = query + " or birthyear='"+dob+"'"; // if date of birth exists, it will take it into account as well
query = query+ "order by givenname"; // ordering by first name
System.out.println("query" + query); // console message
Statement st = conn.createStatement(); // connection statement
ResultSet rs = st.executeQuery(query); // executing our query
while(rs.next())
{
al = new ArrayList();
al.add(rs.getString(1));//id
al.add(rs.getString(2));//dob
al.add(rs.getString(3));//name
al.add(rs.getString(4));//lastname
System.out.println("al :: "+al);
agent_list.add(al);
}
request.setAttribute("agentList",agent_list);

To reiterate what the others are pointing out above, this is "dangerous" code. By not using PreparedStatements, you are opening up yourself to SQL Injection attacks - by which, a malicious user can craft a SQL statement to delete all the data in a table. As #craig-ringer points above, it would be trivial submit data that would delete the table from the database.
Having pointed that out, underlined it several times and highlighted it in a fluorescent yellow mark, lets move on and try to answer your questions:
1) You can query data from multiple tables by using SQL Joins. Here's a PostgreSQL tutorial on JOINS - there are many others out there, I just picked the first one I found.
2) Without the exact data in the database, and the exact parameters being supplied, it is difficult to answer - however, I imagine that the issue is case sensitivity. Comparisons in PostgreSQL are case sensitive - so if the family name in the database is 'Smith' and the parameter is 'smith', no data will be found. So, for simplicity, you'll need to covert both the parameter and the data to the same case e.g. lower. e.g. SELECT * FROM agent where LOWER(familyname)='smith'
I'd also point out that you may run into problems with date formatting - again, this would be addressed using prepared statements.
It appears you are quite new to java, SQL and JDBC; I would suggest you try and follow some tutorials and read some books. There's quite a lot to get to grips with - good luck!

Related

Strange behaviour on select query on date columns

A strange behaviour of select query just came up on my way while im doing a task for the uni.Im pulling data from a table i got on my oracle db.
selectString = "select * from reservation";
prestatement = dbConnection.prepareStatement(selectString);
rs = prestatement.executeQuery(selectString);
while (rs.next()) {
String rdate = rs.getString("reservdate").substring(0, 10);
jComboBox1.addItem(rdate);
//....
//....etc..
The thing is that what is displayed on my combo box is a think like '1999-10-10'
After that i have to pull some data where i must select the ones with the date of the selected item on the combo box.Well there's my problem.
String x = String.valueOf(jComboBox1.getSelectedItem());
selectString="select * from reservation where reservdate='"+x+"'";
//...etc..
After i run that im getting an sql exception with message : Message: ORA-01861: literal does not match format string
I searched a little bit the web and found that if i run this select query everything works fine
selectString="select * from reservation where reservdate='10-OCT-99'";
So my question is, what is the best way to make this work.I mean should i try edit all the dates from combo box to this format? or im doing something wrong all the way and should change that?
Thanks in advance.
You can either:
1- Override your related class' (whatever object that getSelectedItem returns, in this particular case its already a String and you may not need that String.valueOf() call) toString method to achieve the needed format of yours. (Kind of bad to do)
2- Let Oracle DB handle it with its TO_DATE function (Kind of a better practice to do)
"TO_DATE(yourDateString,dateFormat)"
String date = String.valueOf(jComboBox1.getSelectedItem());
selectString="select * from reservation where reservdate= TO_DATE('" + date + "','DD-MON-YY')";
And to prevent SQL injections, using the latter approach with a PreparedStatement would look like this:
String date = String.valueOf(jComboBox1.getSelectedItem());
String selectString="select * from reservation where reservdate= TO_DATE(?,'DD-MON-YY')";
PreparedStatement preStatement = dbConnection.prepareStatement(selectString);
preStatement.setString(1,date);
ResultSet rs = preStatement.executeQuery();
Official Docs

Compare tables on different servers

Using java and SQL Server 2008, I need to compare the content of two tables, the thing to bear in mind is that they are on different servers so I have a connection to the first server (lets call it conn1) and a connection to the second server (lets call it conn2).
I copy the tables into temp tables and then attempt to use the EXCEPT operator to compare the temp tables.
A very basic example of trying to do this in java:
String s1 = "select * into #temp1 from FACTOR";
String s2 = "select * into #temp2 from FACTOR'";
String s3 = "SELECT * FROM #temp1 EXCEPT SELECT * FROM #temp2";
Statement st = null;
ResultSet rs = null;
st = conn1.createStatement();
st.execute(s1);
Statement st1 = null;
ResultSet rs1 = null;
st1 = conn2.createStatement();
st1.execute(s2);
Statement st3 = null;
ResultSet rs3 = null;
st3 = conn2.createStatement();
rs3 = st3.executeQuery(s3);
I'm getting the following error on the last line in the above code snippet:
Stack trace:java.sql.SQLException: Invalid object name '#temp1'.
Is it because I'm using the two connections to the different servers, conn2 can't see #temp1?
Any ideas how I could acheive what I'm trying to do?
Thanks.
What you are trying to do doesn't make sense. Remember that the SQL gets executed on the SQL Server, not in Java. So if the 2 SQL Servers cant see each other, you cant execute queries across SQL Servers that cant see each other.
One solution is to execute the queries on both the servers, and get the data into Java ResultSet, and then process the data in java.
alternatively, copy all the data to one SQL Server, and do your EXCEPT query on that Server
If the SQL Servers can "see" each other, then you can do the whole thing from one connection:
"SELECT * FROM Server1.database.schema.FACTOR
EXCEPT
SELECT * FROM Server2.database.schema.Factor"
I would suggest listing the column names in case they change in the future.
Normal Temp tables are only visible to the connection they are used within. Global temp tables denoted by'##' instead of '#' are visible to multiple connections but disappear when the connection that created them is closed.
This would be better done in a stored procedure using a linked server. e.g.
CREATE PROCEDURE uspCompareTables
AS
BEGIN
select * from Factor
EXCEPT
select * from OTHER_SERVER.dbo.Factor
END
Then you can just call it from your java application. using the normal...
exec uspCompareTables

Fetching records from MySQL using LIKE and %

I have table called mpi which contains 23 columns. I have introduced the search field with button for every column where user can enter the query to fetch the records using query
query="select * from mpi where Genus ='"+genus+"'
Now I want to fetch records by giving keywords using LIKE %% but it is not working and not giving any records but if type type the full name it is working perfectly. Here is the code
String uname=request.getParameter("uname");
String full="%"+uname+"%";
dbconn=new DatabaseConnection();
conn=dbconn.setConnection();
pstmt=conn.prepareStatement("select * from mpi where Genus LIKE ?");
pstmt.setString(1, full);
res=pstmt.executeQuery
Could any one tell me where is the mistake and why I am not getting the records when I use half keyword like %keyword%.
It works (apart from the missing parentheses) and the approach with a prepared statement is entirely correct.
However I have seen a couple of code pieces like that, and always the problem lay with variables mix-up or not closing, or simple oversight. Better declare as close as possible.
try (ResultSet res = pstmt.executeQuery()) {
while (res.next()) {
..
}
} // Automatically closes res.
Also handle the life-cycle of pstmt correctly, with closing.

doing a look-up and writing a query to get the data from sql server

While using Tomcat as the server and Derby as the database I did a look-up and executed the query like :
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/PollDatasource");
Connection connection = ds.getConnection();
// write the query that tells the current weight of actor
String currentWeightQuery = "SELECT " + justPolled + ",total FROM pollresult";
PreparedStatement currentWeight = connection.prepareStatement(currentWeightQuery);
ResultSet cwSet = currentWeight.executeQuery();
Now I am using Microsoft SQL Server 2005 and have to query the database from the java desktop application. What do I need to do query the sql server 2005 ? I have already loaded the sqlserver-jdbc driver and connected to the database but I don't know how to get the data from the database .
Now you need to iterate the ResultSet : Retrieving and Modifying Values from Result Sets.
The ResultSet is actually a wrapper around a cursor in SQL server.
In this case you will probably get only one result.
You need to retrieve the value form the query using one of the getter methods of java.sql.ResultSet, depending on the expected datatype of your query result. As a method parameter you use either the name of the column as a string (""), or the sequence number of the column in the query, staring at 1. (one !)
Try this after your last line of code above:
while (cwSet.next()) {
String string = cwSet.getString(1); // instead of the 1 you can also use the name of the column as a String
int i = cwSet.getInt("total"); //could also have used getInt(2)
// etc...
}

How to add records to databse via sql in Java

I am working a Airsoft application.
I'm trying to add records to a MS Access Database via SQL in Java. I have established a link to the database, with the following:
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
ResultSet rs = stmt.executeQuery("SELECT * FROM AirsoftGunRentals");
tblRent.setModel(DbUtils.resultSetToTableModel(rs));
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I am using Ucanaccess to access my MS database. It is reading the database and is displaying to a JTable. However, I need to create three JButtons to add, delete and update the table. I have tried to code the add button, and I have tried to add a record, but it crashes and gives me errors.
try
{
//String Driver = "sun.java.odbc.JdbcOdbcDriver";
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn = DriverManager.getConnection("jdbc:ucanaccess://" + URL,"","");
Statement stmt = conn.createStatement();
System.out.println("Connection Established!");
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent)"+
"VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
ResultSet rs = stmt.executeQuery(Query);
JOptionPane.showMessageDialog(null, "Success!");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error");
}
I have attempted all three, hoping for a result. But am still getting big errors. The only difference between the buttons is that one adds, one deletes and one updates the table. Other then that, the code is the same, minus variables.
As Brahim mentionned it, you should use stmt.executeUpdate(Query) whenever you update / insert or delete data. Also with this particular query, given your String concatenation (see end of line), there is no space between the ")" and the "VALUES" which probably causes a malformed query.
However, I can see from your code that you are not very experienced with such use-cases, and I'd like to add some pointers before all hell breaks loose in your project :
Use PreparedStatement instead of Statement and replace variables by placeholders to prevent SQL Injection.
The code that you are using here is extremely prone to SQL injection - if any user has any control over any of the variables, this could lead to a full database dump (theft), destruction of data (vandalism), or even in machine takeover if other conditions are met.
A good advice is to never use the Statement class, better be safe than sorry :)
Respect Java Conventions (or be coherent).
In your example you define the String Query, while all the other variables start with lower-case (as in Java Conventions), instead of String query. Overtime, such little mistakes (that won't break a build) will lead to bugs due to mistaking variables with classnames etc :)
Good luck on your road to mastering this wonderful language ! :)
First add a space before the quotation marks like this :
String Query= "INSERT INTO AirsoftGunRentals(NameOfGun, Brand, TypeOfGuns, NumberOfMagazines,Extras,NumberAvailable,UnitRent) "+
" VALUES('"+pName+"','"+pBrand+"','"+pTypeOfGun+"','"+pNumMags+"','"+pExtras+"','"+pNumberAvail+"','"+pRent+"');";
And use stmt.executeUpdate(Query); instead of : stmt.executeQuery(Query);in your insert, update and delete queries. For select queries you can keep it.
I managed to find an answer on how to add, delete and update records to a MS Access DB. This is what I found, after I declared the connection, and the prepped statement. I will try to explain to the best I can. I had to add values individually using this:
(pstmt = Prepped Statement Variable)
pstmt.setWhatever(1,Variable);
And it works fine now. I use the same method to delete and update records.
This is the basic query format:
String SQLInsert = "INSERT INTO Tbl VALUES(NULL,?,?,?,?)";
The NULL in the statement is the autonumber in the table. and .setWhatever() clause replaces the question marks with the data types. Thus manipulating the database.
Thank you everyone for all your contributions. It helped a lot, and made this section a lot more understandable.

Categories

Resources