How to fetch records from Oracle databse using Java - java

I'm learning database with Java using JDBC. I've created a svery basic program after reading some articles on JDBC on the internet. My code is not giving any error but I'm not getting the output also. Here's is my code:
This is my connectivity code: DataService
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DataService {
static Connection con;
public static void main(String args[]){
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:xe","system","scott");
}
catch(Exception e){
System.out.println(e);
}
}
public ResultSet getRecords() {
System.out.println("inside getRecords()");
ResultSet rs=null;
try {
System.out.println("Inside Rs loop");
Statement stmt=con.createStatement();
rs=stmt.executeQuery("select * from emp");
System.out.println("RS before entering while: "+rs);
while(rs.next())
System.out.println("Inside while loop");
System.out.println("Data: " +rs.getInt(0)+" "+rs.getString(1));
} catch (SQLException ex) {
Logger.getLogger(DataService.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Before sending: "+rs);
return rs;
}
}
And here's is my application MainFrame.java
public class MainFrame extends Application {
...
#Override
public void start(Stage primarystage) {
...
try {
System.out.println("Inside try");
DataService dataservice = new DataService();
System.out.println("Result set: "+dataservice.getRecords());
} catch (Exception e) {
//TODO: handle exception
}
}
}
I'm getting this output:
Inside try
inside getRecords()
Inside Rs loop
I cant see any output related to records. Also I've checked select * from emp. There are rows in that table already.
I'm missing out something very important here. Please correct me.

When you create DataService instance DataService dataservice = new DataService(); method main() is not called, therefore variable conn is not initialized and remains null. After that when calling Statement stmt=con.createStatement(); a NullPointerException (NPE) is thrown. This NPE is not catched neither in this catch block catch (SQLException ex) because it catches only SQLExceptions nor in this one catch (Exception e), because there is no handling logic provided.
First step in making code work is adding some exception handling logic in method start() of MainFrame class (never leave empty catch blocks, it's considered as an antipattern).
Then move logic for connection initialization either to getRecords() method making it local variable or to DataService constructor, so variable conn will be initialized, when accessing it.
Next big issue is closing Connection, Statement and ResultSet variables after finishing work with them. Since java 7 you can use try-with-resources syntax to handle such resources.
Also I would recommend to handle ResultSet inside of getRecords() method without exposing it outside DataService class.This class acts as Data Access Object (DAO) and it would be better to keep implementation details inside. Instead you could create some simple Employee class, which instances could be initialized inside while(rs.next()) loop, filled with values from result set and added to some collection. This collection could be returned from getRecords() method.

you should obtain connection instance in same thread as you use it
move connection creation to getRecords method

Related

Java - Oracle Database Change Notification

I am trying to implement a event listener which can identify DATABASE CHANGE NOTIFICATION (Oracle). According to the reference website, it said that event will triggle and print ROW_ID when something change in EXAMPLE table. I want this project running, and it should give me a message "give me something!" if I manually insert/update data in Database. However, it is my understanding that this code will terminate no matter what since there is no infinite loop that can be interrupted by the event. Please correct me if I am wrong.
Additional Question]
By setting OracleConnection.DCN_NOTIFY_ROWIDS as true, it will notify every event including inserting, updating, deleting. Am I correct? I was confused with the meaning of "Database change events will include row-level details, such as operation type and ROWID"
my code:
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
import oracle.jdbc.dcn.DatabaseChangeRegistration;
public class DBTest {
static final String USERNAME = "username";
static final String PASSWORD = "password";
static String URL = "jdbc:oracle:thin:#url:port/name";
public static void main(String[] args) {
DBTest oracleDCN = new DBTest();
try {
oracleDCN.run();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void run() throws Exception {
OracleConnection conn = connect();
Properties prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try {
dcr.addListener(new DatabaseChangeListener() {
public void onDatabaseChangeNotification(DatabaseChangeEvent dce) {
System.out.println("GIVE ME SOMETHING!");
}
});
//conn.unregisterDatabaseChangeNotification(dcr);
Statement stmt = conn.createStatement();
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("select * from Schema.T_TEST");
while (rs.next()) {
}
rs.close();
stmt.close();
} catch (SQLException ex) {
if (conn != null) {
conn.unregisterDatabaseChangeNotification(dcr);
conn.close();
}
throw ex;
}
}
OracleConnection connect() throws SQLException {
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user", DBTest.USERNAME);
prop.setProperty("password", DBTest.PASSWORD);
return (OracleConnection) dr.connect(DBTest.URL, prop);
}
}
More details can be found in the reference website
As you guessed you need keep your main thread alive otherwise your program will exit. You can just make it sleep or do something more useful. Also you can close the JDBC connection but you don't want to close (unregister) the registration immediately. The way Database Change Notification works is with an internal listening thread that runs within the driver. This listening thread will receive outband events sent by the server through a dedicated network socket, process these events and notify the listeners. This listening thread will be closed if you unregister. When you're no longer interested in receiving these events you can create another connection to the database to unregister which will end up closing the driver's listening thread.

Java - Populate a JCombobox with SQLite database

I want to populate a JComboBox with a database column (SQLite).
My database connection is setup through a class called DatabaseConnection setup in anther package.
Here is how it looks like
import java.sql.*;
import javax.swing.JOptionPane;
public class DatabaseConnection {
Connection conn = null;
public static Connection ConnectDB() {
try {
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:database.db");
JOptionPane.showMessageDialog(null, "Connection Established");
conn.setAutoCommit(false);
return conn;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
return null;
}
}
}
In my JFrame class I am creating following method, which according to a youtube tutorial should work
public void PopulateJCB()
{
String queryString = "SELECT DISTINCT [Account Name] FROM main ORDER BY [Account Name]";
try
{
Connection statJCBaccountname = DatabaseConnection.ConnectDB();
Statement stmt = statJCBaccountname.createStatement();
ResultSet rsJCBaccountname = stmt.executeQuery(queryString);
while (rsJCBaccountname.next())
{
comboAccountName.addItem(rsJCBaccountname.getString(1));
}
catch (SQLException e)
{
e.printStackTrace();
}
}
But it displays following errors at "comboAccountName.addItem(rsJCBaccountname.getString(1));"
Multiple markers at this line
- Type safety: The method addItem(Object) belongs to the raw type JComboBox. References to generic type JComboBox<E> should be
parameterized
- comboAccountName cannot be resolved
Please help!
I'm not really sure what you're expecting...
statJCBaccountname isn't even in the code example you've provided, but the compiler is saying that the variable is undefined
There is no such method as createStatement in the DatabaseConnection class
You need to resolve these issues before the program will compile. I'd suggest staying away from YouTube tutorials unless you know the author.
Take a look at JDBC Database Access for more details...

Singleton in JSP, how to properly tidy up on close?

I am just getting started with jsp and my question is this - when I have a singleton class, how do I tidy up after it?
In particular:
public class DBConnection {
private static Connection connection = null;
private static Statement statement = null;
public static ResultSet executeQuery(String query){
if (connection == null) { /*initConnection*/ }
if (statement == null) { /*initStatement*/ }
// do some stuff
}
}
Now, I use this class in several pages to get results from jdbc. However, I need to eventually call statement.close(); and connection.close(); - when should I call those?
I am using singleton, because it felt wrong to call for connection to a database over and over whenever I needed to make a query.
The Connection must be closed always, and after you have executed all your database statements for the desired operations. Two examples:
Case 1: You must show a list of products to user filtered by criteria from database. Solution: get a connection, retrieve a list of products using the filter criteria, close the connection.
Case 2: The client selects some of these products and updates the minimum stock to get an alert and restock them. Solution: get a connection, update all the products, close the connection.
Based on these cases, we can learn lot of things:
You can execute more than a single statement while having/maintaining a single connection open.
The connection should live only in the block where it is used. It should not live before or after that.
Both cases can happen at the same time since they are in a multi threaded environment. So, a single database connection must not be available to be used by two threads at the same time, in order to avoid result problems. For example, user A searches the products that are in category Foo and user B searches the products that are in category Bar, you don't want to show the products in category Bar to user A.
From last sentence, each database operation ((or group of similar operations like Case 2) should be handled in an atomic operation. To assure this, the connection must not be stored in a singleton object, instead it must be live only in the method being used.
In consequence:
Do not declare the Connection nor the Statement nor the ResultSet nor other JDBC resource as static. It will simply fail. Instead, declare only the Connection as field of your DBConnection class. Let each method decide to handle each Statement (or PreparedStatement) and ResultSet and specific JDBC resources.
Since you must close the connection after its usage, then add two more methods: void open() and void close(). These methods will handle the database connection retrieval and closing that connection.
Additional, since the DBConnection looks like a wrapper class for Connection class and database connection operations, I would recommend to have at least three more methods: void setAutoCommit(boolean autoCommit), void commit() and void rollback(). These methods will be plain wrappers for Connection#setAutoCommit Connection#close and Connection#rollback respectively.
Then you can use the class in this way:
public List<Product> getProducts(String categoryName) {
String sql = "SELECT id, name FROM Product WHERE categoryName = ?";
List<Product> productList = new ArrayList<Product>();
DBConnection dbConnection = new DBConnection();
try {
dbConnection.open();
ResultSet resultSet = dbConnection.executeSelect(sql, categoryName); //execute select and apply parameters
//fill productList...
} catch (Exception e) {
//always handle your exceptions
...
} finally {
//don't forget to also close other resources here like ResultSet...
//always close the connection
dbConnection.close();
}
}
Note that in this example the PreparedStatement is not in the getProducts method, it will be a local variable of the executeSelect method.
Additional notes:
When working in an application server, you should not open connections naively e.g. using Class.forName("..."), instead use a database connection pool. You can roll on some database connection pooling libraries like C3P0 as explained here: How to establish a connection pool in JDBC?. Or configure one in your application server, as I explain here: Is it a good idea to put jdbc connection code in servlet class?
If this is for learning purposes, then roll on your own classes to handle the communication with your database. In real world applications, this is not recommended (doesn't mean you should not do it). Instead, use a database connectivity framework like ORMs e.g. JPA (Java official ORM framework) or Hibernate; there are no ORM frameworks that handles database communication like Spring JDBC and MyBatis. The choice is yours.
More info:
Should a database connection stay open all the time or only be opened when needed?
How do servlets work? Instantiation, sessions, shared variables and multithreading. Not directly related to your question, but it will help you understand why to not maintain state in resources that are used in multithreaded environments.
Define connection resource in mywebapp/META-INF/context.xml file
<Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
maxActive="10" maxIdle="2" maxWait="20000"
driverClassName="com.mysql.jdbc.Driver"
username="myuser" password="mypwd"
url="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8"
validationQuery="SELECT 1" />
Create DB.java helper class to minimize code in other parts of app
import java.sql.*;
import javax.sql.DataSource;
import javax.naming.Context;
import javax.naming.InitialContext;
public class DB {
public static Connection createConnection() throws SQLException {
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb");
return ds.getConnection();
} catch (SQLException ex) {
throw ex;
} catch (Exception ex) {
SQLException sqex = new SQLException(ex.getMessage());
sqex.initCause(ex);
throw sqex;
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) try { rs.close(); } catch (Exception e) { }
if (stmt != null) try { stmt.close(); } catch (Exception e) { }
if (conn != null) try { conn.close(); } catch (Exception e) { }
}
public static void close(ResultSet rs, boolean closeStmtAndConn) {
if (rs==null) return;
try {
Statement stmt = rs.getStatement();
close(rs, stmt, stmt!=null ? stmt.getConnection() : null);
} catch (Exception ex) { }
}
}
And somewhere in your app DAO code use DB helper.
public List<MyBean> getBeans() throws SQLException {
List<MyBean> list = new ArrayList<MyBean>();
ResultSet rs=null;
try {
Connection con = DB.createConnection();
String sql = "Select * from beantable where typeid=?";
PreparedStatement stmt = con.prepareStatement(sql, Statement.NO_GENERATED_KEYS);
stmt.setInt(1, 101);
rs = stmt.executeQuery();
while(rs.next()
list.add( createBean(rs) );
} finally {
DB.close(rs, true); // or DB.close(rs, stmt, conn);
}
return list;
}
private MyBean createBean(ResultSet rs) throws SQLException {
MyBean bean = new MyBean();
bean.setId( rs.getLong("id") );
bean.setName( rs.getString("name" );
bean.setTypeId( rs.getInt("typeid") );
return bean;
}
I would add two methods to the class:
public static void open() throws SomeException;
public static void close() throws SomeException;
then your calling code looks something like this{
try {
DBConnection.open();
... code to use the connection one or more times ...
} finally {
DBConnection.close();
}
Wrap all your database calls inside that and it will take care of closing whether there is an exception thrown or not.
Of course, this isn't much different than having a regular class, which I might recommend:
try {
DBConnection conn = new DBConnection();
conn.open();
... all the code to use the database (but you pass 'conn' around) ...
} finally {
conn.close();
}
And you might want to look at the java.lang.AutoCloseable and java.io.Closeable to see if that helps you.
2
If you are keeping it open across page loads, there isn't any place to put the try ... finally stuff so you can open it and close it when the servlet closes or the server closes or something like that.
If you are going to leave it open, you need to make sure and add code to verify it doesn't close when you aren't looking. A short network glitch, for example, could close it down. In that case, you need to reopen it when it gets closed. Otherwise, all database access from that point will fail.
You might want to look into the concept of a DataBase Pool. Apache has one -- DBCP. Tomcat has its own that's quite good. Other containers, like JBOSS, WebSphere, WebLogic all have them. There's a couple that can be used with the Spring Framework. What it does is manage one or more database connections. Your code asks it for one and it returns an open one, unless none is available and then it opens one and returns it. You call close when your code gets through with it but it doesn't really close the connection, it just returns it to the pool.
You can usually configure the pool to check for shut down connections and reopen if needed.

Executing JDBC MySQL query with this custom method

I've been doing my homework and I decided to re-write my vote4cash class which manages the mysql for my vote4cash reward system into a new class called MysqlManager. The MysqlManager class I've made needs to allow the Commands class to connect to mysql - done and it needs to allow the Commands class to execute a query - I need help with this part. I've had a lot more progress with the new class that I've made but I'm stuck on one of the last, most important parts of the class, again, allowing the commands class to execute a query.
In my MysqlManager class I have put the code to connects to MySql under
public synchronized static void createConnection() {
Now I just need to put the code that allows the Commands class to execute a query under this as well. I've researched and tried to do this for a while now, but I've had absolutely no luck.
The entire MysqlManager class:
package server.util;
/*
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
*/
import java.sql.*;
import java.net.*;
import server.model.players.Client;//Will be needed eventually so that I can reward players who have voted.
/**
* MySQL and Vote4Cash Manager
* #author Cloudnine
*
*/
public class MysqlManager {
/** MySQL Connection */
public static Connection conn = null;
public static Statement statement = null;
public static ResultSet results = null;
public static Statement stmt = null;
public static ResultSet auth = null;
public static ResultSet given = null;
/** MySQL Database Info */
public static String DB = "vote4gold";
public static String URL = "localhost";
public static String USER = "root";
public static String PASS = "";
public static String driver = "com.mysql.jdbc.Driver"; //Driver for JBDC(Java and MySQL connector)
/** Connects to MySQL Database*/
public synchronized static void createConnection() {
try {
Class.forName(driver);
conn = DriverManager.getConnection(URL + DB, USER, PASS);
conn.setAutoCommit(false);
stmt = conn.createStatement();
Misc.println("Connected to MySQL Database");
}
catch(Exception e) {
//e.printStackTrace();
}
}
public synchronized static void destroyConnection() {
try {
statement.close();
conn.close();
} catch (Exception e) {
//e.printStackTrace();
}
}
public synchronized static ResultSet query(String s) throws SQLException {
try {
if (s.toLowerCase().startsWith("select")) {
ResultSet rs = statement.executeQuery(s);
return rs;
} else {
statement.executeUpdate(s);
}
return null;
} catch (Exception e) {
destroyConnection();
createConnection();
//e.printStackTrace();
}
return null;
}
}
The snippet of my command:
if (playerCommand.equals("claimreward")) {
try {
PreparedStatement ps = DriverManager.getConnection().createStatement("SELECT * FROM votes WHERE ip = hello AND given = '1' LIMIT 1");
//ps.setString(1, c.playerName);
ResultSet results = ps.executeQuery();
if(results.next()) {
c.sendMessage("You have already been given your voting reward.");
} else {
ps.close();
ps = DriverManager.getConnection().createStatement("SELECT * FROM votes WHERE ip = hello AND given = '0' LIMIT 1");
//ps.setString(1, playerCommand.substring(5));
results = ps.executeQuery();
if(results.next()) {
ps.close();
ps = DriverManager.getConnection().createStatement("UPDATE votes SET given = '1' WHERE ip = hello");
//ps.setString(1, playerCommand.substring(5));
ps.executeUpdate();
c.getItems().addItem(995, 5000000);
c.sendMessage("Thank you for voting! You've recieved 5m gold!");
} else {
c.sendMessage("You haven't voted yet. Vote for 5m gold!");
}
}
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return;
How the command works:
When a player types ::commandname(in this case, claimreward), the commands function will be executed. This isn't the entire commands class, just the part that I feel is needed to be posted for my question to be detailed enough for a helpful answer.
Note: I have all my imports.
Note: Mysql connects successfully.
Note: I need to make the above command code snippet able to execute mysql queries.
Note: I prefer the query to be executed straight from the command, instead of from the MysqlManager, but I will do whatever I need to resolve this problem.
I feel that I've described my problem detailed and relevantly enough, but if you need additional information or understanding on anything, tell me and I'll try to be more specific.
Thank you for taking the time to examine my problem. Thanks in advance if you are able to help.
-Alex
Your approach is misguided on many different levels, I can't even start to realize what should be done how here.
1) Don't ever use static class variables unless you know what you do there (and I'm certain, you don't)
2) I assume there is a reason you create your own jdbc connection (e.G. its part of your homework) if not, you shouldn't do that. I see you use DriverManager and PreparedStatement in one part, you should continue to use them.
3) Your approach seems to intend to start with a relative good code base (your command part) and then goes to a very low-level crude approach on database connections (your MysqlManager) unless really necessary and you know what you do, you should stay on the same level of abstraction and aim for the most abstract that fits your needs. (In this case, write MysqlManager the way you wrote Command)
4) In your previous question (that you just assumed everybody here has read, which is not the case) you got the suggestion to redesign your ideas, you should do that. Really, take a class in coding principles learn about anti-patterns and then start from scratch.
So in conclusion: Write at least the MysqlManager again, its fatally broken beyond repair. I'm sorry. Write me an email if you have further questions, I will take my time to see how I can help you. (an#steamnet.de)

Separate database connection method for jsp and servlets

I was trying to write a separate database connection method in .java file which can be called upon by any servlet or jsp file needing the database connection. My code is
import java.sql.*;
import java.lang.*;
public class ConnectionClass {
private String username="root";
private String password="passwd";
/* Adjust the above two as per the username
* password combination of your MySql databse */
public Connection connect()
{
try
{
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost/schooldatabase";
Connection con = DriverManager.getConnection(url,username,password);
return con;
}
catch(Exception e)
{
response.sendRedirect("studentserr.html");
out.println(e);
}
}
}
Now, the problem is that i'll be returning a Connection type so that all the servlets (which require database connection) may use it to execute various statements. However, in my code what should i return in the catch block ( which means that the connection to the database could not be established) ? Also, in case of a connection failure, I'm redirecting the user to the following page:
"studentserr.html"
This works fine if i use it in a servlet but not in .java class. What should i do for this ??
You should only be catching exceptions at exactly that moment where you can sensibly deal with them. You can't sensibly deal with them in the getConnection() method, so you should instead throw it so that the caller itself needs to deal with it.
Displaying an error page in case of a specific exception is however the responsibility of the servlet container itself. You normally configure the error page in web.xml as follows:
<error-page>
<exception-type>java.sql.SQLException</exception-type>
<location>/WEB-INF/errorpages/database.jsp</location>
</error-page>
You only need to change your code accordingly that you never catch the exception, or at least rethrow as ServletException where necessary.
Here's a minor rewrite:
public class Database {
private String url = "jdbc:mysql://localhost/schooldatabase";
private String username = "root";
private String password = "passwd";
static {
try {
Class.forName("com.mysql.jdbc.Driver"); // You don't need to load it on every single opened connection.
} catch (ClassNotFoundException) {
throw new ExceptionInInitializerError("MySQL JDBC driver missing in classpath", e);
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
}
And here's how you should use it in your DAO classes:
public List<Student> list() throws SQLException {
List<Student> students = new ArrayList<Student>();
Connection connection = null;
// ...
try {
connection = Database.getConnection();
// ...
} finally { // Note: no catch block!
// ...
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
return students;
}
And here is how you should use the DAO class in your servlet's doGet() or doPost().
try {
List<Student> students = studentDAO.list();
request.setAttribute("students", students);
request.getRequestDispatcher("/WEB-INF/students.jsp").forward(request, response);
} catch (SQLException e) {
throw new ServletException(e);
}
It has to be rethrown as ServletException simply because you can't add SQLException to the throws clause of any HttpServlet method. The servletcontainer will unwrap the SQLException while locating the error page.
Return a null value in case an exception is thrown. In case of getting a null value from your method, handle the exception and don't perform any database operation.
Also, remember to separate the database logic (connection, statement execution) from the business logic and the presentation. In your actual method, this code
response.sendRedirect("studentserr.html");
should never be in the database logic, because is presentation logic.
More info:
Java 101: Layered Architecture
How to avoid Java Code in JSP-Files?
Try moving class "ConnectionClass" into some package. and then call using this package in your java class where you require this (seems to be classpath issue in java file) or in jsp or servlet page.
Example
You need this in Demo.java as
pkg1.ConnectionClass obj = new pkg1.ConnectionClass ();
It is recommended to have database connection class as singleton. So that through out the application only a single instance of connection will be created and shared.

Categories

Resources