I am currently creating a private method inside a servlet. But my PreparedStatement keeps returning null.
private ArrayList<String> emails(String id) {
ArrayList<String> email= new ArrayList<String>();
try {
PreparedStatement st = null;
ResultSet data = null;
DriverManager.getConnection(
"jdbc:postgresql://localhost/test",
"test", "test");
String sql = "SELECT email FROM hdpr.email_table WHERE id='"
+ id+ "'";
data = st.executeQuery(sql);
while (data.next()) {
email.add(data.getString("email"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
e.getMessage();
}
return email;
}
Try it like this:
private ArrayList<String> emails(String id) {
ArrayList<String> email= new ArrayList<String>();
try {
PreparedStatement st = null;
ResultSet data = null;
// Creating a new connection
Connection con = DriverManager.getConnection(
"jdbc:postgresql://localhost/test",
"test", "test");
// your SQL Query now with a ? as parameter placeholder
String sql = "SELECT email FROM hdpr.email_table WHERE id = ?";
// creating a new preparedStatement using your sql query
st = con.prepareStatement(sql);
// set the first ? to the value of id
st.setString(1, id);
data = st.executeQuery();
while (data.next()) {
email.add(data.getString("email"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
System.err.println(e.getMessage());
}
return email;
}
Steps you should also have a look to:
If you assign null to a variable it will be null the NullpointerException will always occur if you try to call a method from that object.
To use your PreparedStatement st you need to initialize it by creating preparedStatement using your connection and also your SQL query.
Don't add parameters to a SQL query using the + operator - this will open doors for SQL Injection for this we have the prepared statement and setString(), setInt(), ...
You should have a look at tutorials like let's say this: http://www.mkyong.com/jdbc/jdbc-preparestatement-example-select-list-of-the-records/
Related
How to Close Statements and Connection in This Method
public static ResultSet getData (String query){
try {
Connection con = ConnectionProvider.connect();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
return rs;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
System.out.println(e);
return null;
}
You need to close connections in finally block:
try {
...
}
catch {
...
}
finally {
try { st.close(); } catch (Exception e) { /* Ignored */ }
try { con.close(); } catch (Exception e) { /* Ignored */ }
}
In Java 7 and higher you can define all your connections and statements as a part of try block:
try(Connection con = ConnectionProvider.connect();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
) {
// Statements
}
catch(....){}
One should use try-with-resources to automatically close all.
Then there is the p
public static void processData (String query, Consumer<ResultSet> processor){
try (Connection con = ConnectionProvider.connect();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query)) {
processor.accept(rs);
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e);
System.getLogger(getClass().getName()).log(Level.Error, e);
}
}
processData("SELECT * FROM USERS", rs -> System.out.println(rs.getString("NAME")));
Or
public static <T> List<T> getData (String query, UnaryOperator<ResultSet, T> convert){
try (Connection con = ConnectionProvider.connect();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query)) {
List<T> result = new ArrayList<>();
while (rs.next()) {
result.add(convert.apply(rs));
}
return result;
} catch (SQLException e) {
System.getLogger(getClass().getName()).log(Level.Error, e);
throw new IllegalArgumentException("Error in " + query, e);
}
}
Then there is the danger with this function, that users will compose query strings like:
String query = "SELECT * FROM USERS WHERE NAME = '" + name + "'";
Which does not escape the apostrophes like in d'Alembert. It opens the gates to SQL injection, a large security breach. One needs a PreparedStatement, and then can use type-safe parameters.
As with try-with-resources the code already is reduced (no explicit closes), you should drop this kind of function. But almost most programmers make this mistake.
I have a GUI JDBC SQL project. I can read the information from my Database well but i don't know what is wrong with my create,update,delete method. Seem like some methods in resultSet doesn't work correctly. My code is below.
public Person create(Person p){
try {
rs.moveToInsertRow();
rs.updateInt("PersonID", p.getPersonID());
rs.updateString("firstName", p.getFirstName());
rs.updateString("middleName", p.getMiddleName());
rs.updateString("lastName", p.getLastName());
rs.updateString("email", p.getEmail());
rs.updateString("phone",p.getPhone());
rs.insertRow();
rs.moveToCurrentRow();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return p;
}// end of create method
public Person update(Person p){
try {
rs.updateString("firstName", p.getFirstName());
rs.updateString("middleName", p.getMiddleName());
rs.updateString("lastName", p.getLastName());
rs.updateString("email", p.getEmail());
rs.updateString("phone",p.getPhone());
rs.updateRow();
rs.moveToCurrentRow();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return p;
}//end of update method
public void delete(){
try {
rs.moveToCurrentRow();
rs.deleteRow();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end of delete method
thanks for your reading.
public PersonBean() {
try {
Class.forName(JDBC_DRIVER);
Connection con = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
sm = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rs = sm.executeQuery("Select * From Person");
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end of PersonBean
my connection to SQL is OK because i can read information from SQL but i cant write data to SQL. Here is my error when i try to create a new Person.
com.microsoft.sqlserver.jdbc.SQLServerException: The result set is not updatable.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.throwNotUpdatable(SQLServerResultSet.java:436)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.verifyResultSetIsUpdatable(SQLServerResultSet.java:447)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.moveToInsertRow(SQLServerResultSet.java:4350)
at PersonBean.create(PersonBean.java:29)
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. An updatable result set allows modification to data in a table through the result set. The following code makes a result set that is scrollable and insensitive to updates by others:
try {
// Create a statement that will return updatable result sets
Statement stmt = connection.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
//Primary key EmployeeID must be specified
//so that the result set is updatable
ResultSet resultSet = stmt.executeQuery(
"SELECT EmployeeID, Name, Office FROM employees");
} catch (SQLException e) {
}
You want to use following example and check this codes with your codes in project:
//database connector file example (com.mysql.jdbc.Driver)
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
String DB_URL = "jdbc:mysql://localhost:3306/dbname";
String DB_USER = root;
String DB_PASS = "";
Connection con = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
Statement stmt = con.createStatement();
stmt.executeQuery("Select * From Person");
ResultSet resultSet = stmt.getResultSet();
while(resultSet .next()){
System.out.print(resultSet.getString("fieldName");
//and other your field to display
}
resultSet.close();
stmt.close()
} catch(Exceptoin e) {
....
}
There are many examples of this approach for insert, update and delete.
What I did wrong? I tried to swap rs.close(), pstmt.close(), conn.close().
I created a PreparedStatement.
But I still can not display the contents of a database table. If I remove conn.close(), everything works! How close the connection and get an output on the jsp?
This is my code:
public ResultSet executeFetchQuery(String sql) {
ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = Database.getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException ex) {
Logger.getLogger(PhoneDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
return rs;
}
public ArrayList<Phone> getAllPhone() {
ArrayList<Phone> list = new ArrayList<>();
String sql = "SELECT * FROM phones.product;";
ResultSet rs = executeFetchQuery(sql);
try {
while (rs.next()) {
Phone phone = new Phone();
phone.setId(rs.getInt("id"));
phone.setName(rs.getString("name"));
phone.setPrice(rs.getInt("price"));
phone.setQuantity(rs.getInt("quantity"));
phone.setDescription(rs.getString("description"));
System.err.println(phone);
list.add(phone);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
return list;
}
ResultSet rs = executeFetchQuery(sql);
The above statement closes everything.
Actually your code should be
DBConnection
Iterate through result set
Store the values/display the value directly(depends on your need)
Finally close the connection.
Which is the proper way to access the data from db.
The more common pattern for this kind of process is to maintain the connection and the statement outside the main query code. This is priomarily because connections would generally be allocated from a pool as they are expensive to create and preparing the same statement more than once is wasteful.
Something like this is most likely to work both efficiently and correctly.
static final Connection conn = Database.getConnection();
static final String sql = "SELECT * FROM phones.product;";
static final PreparedStatement pstmt = conn.prepareStatement(sql);
public ArrayList<Phone> getAllPhone() {
ArrayList<Phone> list = new ArrayList<>();
ResultSet rs = pstmt.executeQuery();
try {
while (rs.next()) {
Phone phone = new Phone();
phone.setId(rs.getInt("id"));
phone.setName(rs.getString("name"));
phone.setPrice(rs.getInt("price"));
phone.setQuantity(rs.getInt("quantity"));
phone.setDescription(rs.getString("description"));
System.err.println(phone);
list.add(phone);
}
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
rs.close();
}
return list;
}
Note how the ResultSet is closed in a finally block to stop leaks.
There are variations of this pattern which, for example, only create the connection and prepare the statement at the last minute rather than as static final fields like I have here.
I am pretty new to Java so I'm working on a project to develop my knowledge with databases and Java.
I have figured out how to add queries into the database but now I'm getting errors when trying to print them out.
Assume I already have everything that's necessary imported in such as the scanner and sql statements
Here is my connection class which is named MainClass:
public static Connection getConnection() throws Exception {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/testTable";
String username = "placeholder";
String password = "placeholder";
Class.forName(driver);
Connection conn = Driver Manager.getConnection(url, username, password);
return conn;
}
Now in a different class if the user types !lookup and a word I want the definition of that word to be retrieved from the table whose name is dictionary and columns are word, definition:
String userSearch = user_input.next();
String[] userSearchSplit = userSearch.split(" ", 3);
if (userSearchSplit[0].equals("!lookup")) {
try {
conn = MainClass.getConnection();
String query = "select definition from dictionary where word=" + userSearchSplit[1];
ResultSet result = pstmt.executeQuery(query);
while (result.next()) {
String definition = result.getString("definition");
System.out.println(definition);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
At the end of all this when I try to look up a word I put in the table before running I get:
java.lang.NullPointerException
Check if your user_input is null?
I am assuming your code:
ResultSet result = pstmt.executeQuery(query);
as
Statement pstmt = conn.createStatement();
ResultSet result = pstmt.executeQuery(query);
Or it could be that you have not initialized the pstmt properly
When i run my website it on glassfish server everything works fine but after some time its stop responding and I need to restart glassfish.. I think its cause I not closing the connection. Can someone tell me if this is the problem? if yes how to close it? Here is one of my function.
public Album get_album (String title)
{
try{
//creates a connection to the server
Connection cn = getCon().getConnection();
//prepare my sql string
String sql = "SELECT * FROM albums WHERE Title = ?";
//create prepared statement
PreparedStatement pst = cn.prepareStatement(sql);
//set sql parameters
pst.setString(1, title);
//call the statement and retrieve results
ResultSet rs = pst.executeQuery();
if(rs.next()) {
Album a = new Album();
a.setIdAlbum(rs.getInt("idAlbum"));
a.setTitle(rs.getString("Title"));
a.setYear(rs.getInt("Year"));
a.setIdArtist(rs.getInt("idArtist"));
a.setIdUser(rs.getInt("idUser"));
a.setLike(rs.getInt("Like"));
a.setDislike(rs.getInt("Dislike"));
a.setNeutral(rs.getInt("Neutral"));
a.setViews(rs.getInt("Views"));
return a;
}
}
catch (Exception e) {
String msg = e.getMessage();
}
return null;
}
Assumming the unique error in your application is for not closing the resources after using them, your code should change to:
public Album get_album (String title) {
Connection cn = null;
PreparedStatement pst = null;
ResultSet rs = null;
Album a = null;
try{
//creates a connection to the server
cn = getCon().getConnection();
//prepare my sql string
String sql = "SELECT * FROM albums WHERE Title = ?";
//create prepared statement
pst = cn.prepareStatement(sql);
//set sql parameters
pst.setString(1, title);
//call the statement and retrieve results
rs = pst.executeQuery();
if (rs.next()) {
a = new Album();
a.setIdAlbum(rs.getInt("idAlbum"));
a.setTitle(rs.getString("Title"));
a.setYear(rs.getInt("Year"));
a.setIdArtist(rs.getInt("idArtist"));
a.setIdUser(rs.getInt("idUser"));
a.setLike(rs.getInt("Like"));
a.setDislike(rs.getInt("Dislike"));
a.setNeutral(rs.getInt("Neutral"));
a.setViews(rs.getInt("Views"));
//don't return inside try/catch
//return a;
}
} catch (Exception e) {
String msg = e.getMessage();
//handle your exceptions
//e.g. show them in a logger at least
e.printStacktrace(); //this is not the best way
//this will do it if you have configured a logger for your app
//logger.error("Error when retrieving album.", e);
} finally {
closeResultSet(rs);
closeStatement(pst);
closeConnection(cn);
}
return a;
}
public void closeConnection(Connection con) {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
//handle the exception...
}
}
}
public void closeStatement(Statement st) {
if (st!= null) {
try {
st.close();
} catch (SQLException e) {
//handle the exception...
}
}
}
public void closeResultSet(ResultSet rs) {
if (rs!= null) {
try {
rs.close();
} catch (SQLException e) {
//handle the exception...
}
}
}