I have a Java application and I want to use SQL database. I have a class for my connection :
public class SQLConnection{
private static String url = "jdbc:postgresql://localhost:5432/table";
private static String user = "postgres";
private static String passwd = "toto";
private static Connection connect;
public static Connection getInstance(){
if(connect == null){
try {
connect = DriverManager.getConnection(url, user, passwd);
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Connection Error", JOptionPane.ERROR_MESSAGE);
}
}
return connect;
}
}
And now, in another class I succeeded to print my values but when I attempt to insert a value nothing is happening ...
Here's my code :
try {
Statement state = SQLConnection.getInstance().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
Statement state2 = SQLConnection.getInstance().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
state2.executeUpdate("INSERT INTO table(field1) VALUES (\"Value\")"); // Here's my problem
ResultSet res = state.executeQuery("SELECT * FROM table");
You need to commit (and close) the connection (and statement) after use. You also need to ensure that you aren't swallowing any SQLExceptions which may cause that you see "nothing" to happen.
That said,
private static Connection connect;
This is a terribly bad idea. You should never declare external resources as static in your application. Your application will break when the other side decides to close the resource because it's been released for a too long time. You really need to acquire and close those resources (Connection, Statement and ResultSet in the shortest possible scope. I.e. inside the very same method block as where the query is to be executed.
Also, I strongly recommend to use PreparedStatement instead of Statement since that will prevent your code from SQL injection attacks.
You may find this article useful to learn more about how to do basic JDBC interaction the right way.
state2.executeUpdate("INSERT INTO table(field1) VALUES (\"Value\")");
should be:
state2.executeUpdate("INSERT INTO plateau(field1) VALUES (\"Value\")");
Copuld just be a copy over to SO error, but looking but shoulding INSERT INTO table(field1) be INSERT INTO plateau(field1)?
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I am working on a JavaFX project that connects to a MySQL database (and as such I use a JDBC [java.sql] to perform various tasks from java to SQL). I've recently come into a lot of confusion regarding the standard procedure of connecting to a database.
From what I understand, I should create one instance of a Connection object, then I should pass this instance around the project until the end of the entire program.
Connection connection = DriverManager.getConnection(url, username, password);
If the statement above is true then I only need to call the previous line once in the entire program and pass the connection variable around the entire program whenever I need to connect to the database. If this is true, how can I pass around this instance of connection from one controller class to another?
Furthermore, I am seeing that it is a standard procedure (in order to maximize GUI responsiveness) to push all "costly" procedures onto another thread (not the main one that is handling the GUI) using the javafx.concurrencies library. If this statement is true, is it also true that I should push all methods that interact with the database into say a Task<V> class?
Up until now, I created multiple object classes that each communicate with the database. In addition, I created a Database class that allows me to initialize a "new" connection to the database. For example,
public class Database {
public static Connection createConnectionToDB() throws SQLException{
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
}
Now in the various object classes, when I need to add, update, or delete some data from the database, I created an add, update, and delete method in each object to handle that object's data in the database. However, for each method, I thought (from my natural naivete) that it would be standard to first create a connection to the database via the previous Connection connection = createConnectionToDB() method in the Database class then to use this connection instance to do what needs to be done, then close the connection with the connection.close() method.
For example,
public class Object{
add(){
Connection connection = Database.createConnectionToDB();
PreparedStatement statement = ...
// some other lines
connection.close();
}
update(){
Connection connection = Database.createConnectionToDB();
PreparedStatement statement = ...
// some other lines
connection.close();
}
delete(){
Connection connection = Database.createConnectionToDB();
PreparedStatement statement = ...
// some other lines
connection.close();
}
}
That is, for each object, and each method for each object, a new connection is created and closed. Is this bad practice?
It could be a bad practice if your application creates new database Connection objects with longer scopes every time it needs to perform a query operation on the database. I would suggest that you should put the Connection initiation code into a try-with-resources code block so that for each database operation, a connection is established, query operation is performed and the connection is closed within the block. The class to fetch new Connection could look like this:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static final String DB_URL = "jdbc:mysql://localhost/dbName";
private static final String USER = "dbUser";
private static final String PASS = "dbPassword";
public static Connection getDatabaseConnection()
{
Connection databaseConnection;
try {
databaseConnection = DriverManager.getConnection(DB_URL, USER, PASS);
} catch (SQLException e)
{
e.printStackTrace();
}
return databaseConnection;
}
}
So, you can make a call to the static method DatabaseConnection.getDatabaseConnection() from any point (controller or other class) of your application to obtain the new Connection instance and use it.
And yes, it would be better to make use of the javafx.concurrency library in case of a JavaFX application. You can utilize the Task<V> class like:
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
String query = "SELECT id, first, last, age FROM Employees";
try(Connection conn = DatabaseConnection.getDatabaseConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);) {
// Extract data from result set
while (rs.next()) {
// Retrieve by column name
System.out.print("ID: " + rs.getInt("id"));
System.out.print(", Age: " + rs.getInt("age"));
System.out.print(", First: " + rs.getString("first"));
System.out.println(", Last: " + rs.getString("last"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
};
And invoking the Task by:
new Thread(task).start();
Note that you should populate all the ResultSet data into your own custom non-jdbc classes so that the ResultSet class can also be disposed within the block. Furthermore, you should also consider applying Transaction Management to your code containing Database Operations (in case your application is concurrently making many database calls from different points/classes) for data consistency.
I started learning databases in java with postgres. I created database and now need to add there some data. I can add data succesfully only one time, then i get SQLException and can't add anything to database, so i need to launch my project again. Where did i go wrong?
Here is method for adding: (if its not enough, i can add what is needed)
public final Connection CONNECTION = DriverManager.getConnection
(url, login, pass);
public void sqlAddData(Algorithm codec, String input, String translated) throws SQLException {
try (CONNECTION) {
java.sql.Timestamp date = new java.sql.Timestamp(new java.util.Date().getTime());
String add = " insert into db.public.history ( codec, input, translated, date) values(?,?,?,?)";
PreparedStatement prepared = CONNECTION.prepareStatement(add);
prepared.setString(1, String.valueOf(codec));
prepared.setString(2, input);
prepared.setString(3, translated);
prepared.setTimestamp(4, date);
prepared.executeUpdate();
} catch (SQLException e) {
logger.warning("Error with database");
}
CONNECTION.close();
}
Thanks for help and i'm sorry, if it is noob question, i'm just learning.
Its because you close the connection after one call.
CONNECTION.close(); is the last thing you do and that closes the connection, if u wanna add data again you need to open the connection once again, or wait to close when you dont wanna add anything more.
In your code you instantiate your connection before your method with :
public final Connection CONNECTION = DriverManager.getConnection(url, login, pass);
Which means, if you close it inside your method you will not be able to reuse this connection unless you create a new one (instantiate a new one).
To fix your problem here is what you can do :
public final Connection CONNECTION;
public void sqlAddData(Algorithm codec, String input, String translated) throws SQLException {
CONNECTION = DriverManager.getConnection(url, login, pass);
try (CONNECTION) {
java.sql.Timestamp date = new java.sql.Timestamp(new java.util.Date().getTime());
String add = " insert into db.public.history ( codec, input, translated, date) values(?,?,?,?)";
PreparedStatement prepared = CONNECTION.prepareStatement(add);
prepared.setString(1, String.valueOf(codec));
prepared.setString(2, input);
prepared.setString(3, translated);
prepared.setTimestamp(4, date);
prepared.executeUpdate();
} catch (SQLException e) {
// Handle your exception correctly or throw it.
}
}
Note you can also use try-catch-finally to safely close your connection. I didn't show you how to catch your exception I will let you do some digging yourself ;)
Also note that you are using try-with-resources which remove the finally block and still close your connection safely.
Hope this helps.
The reason you can only connect to the database one time is because you're closing the open connection by wrapping the Connection object in a try-with-resources statement. Also, you're calling close on Connection after that statement which is redundant.
A solution to this problem would be to use connection pooling. Some good options are Hikari and C3P0.
I try to create a connection between JDBC and MS Access.
I follow the instruction as per this link. I am using IntelliJ Idea. Here I am sharing some snaps to describe my problem.
This is the code that I write down to make a connection with Database Database2. But as you can see there is no error neither any output. Now I am sharing the table structure and content on the table.
2nd picture is
My code is:
import java.sql.*;
public class Connection_sample {
public static void main(String[] args) {
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
Connection conn= DriverManager.getConnection("jdbc:ucanaccess://D://tutorial/Database2.accdb");
Statement s = conn.createStatement();
s.executeQuery("select * from Student");
ResultSet rset = s.getResultSet();
while (rset.next()) {
System.out.println(rset.getInt(1)+""+rset.getInt(2));
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Can anyone help me to find the error?
Your problem is the result of using getResultSet() instead of using the result set returned by executeQuery(). You should only use getResultSet() in combination with execute().
A result set should only be obtained once, and it was already returned from executeQuery (which you ignored). When you called getResultSet, you - apparently - got an empty one (which technically violates the contract).
I know this probably is a similar question from the rest, (well originally, before I tried something new, it was a bit unique but it never solved the main problem), but I probably need to discuss this with someone who can help because I could never get what's causing this despite already reading various posts from this site. Bottom line is I need to keep on making plenty of sequential queries but I ended up making too many connections.
What my program does is that it displays data about each member and that it's sort of a tree or network where, in order to get the data you need for each member, you have to scout through every other member that points to that current member (or child's data) , and the data of the member that points to the member that points to the current member (or grandchild's data) and so on. Hence, why I need to keep making queries cause I need to get the data off of each child. Each node has I think a minimum children of 5 and on my 34th member, it gave off that "Too Many Connections" error.
I have read how to open and close the Connections and all but am I still doing it incorrectly? I've tried changing the max connections but that's not really a long term solution for me. Here's how I do it:
public class SQLConnect {
private Connection con;
private Statement st;
private ResultSet rs;
public SQLConnect() {
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname?zeroDateTimeBehavior=convertToNull", "root", "");
st = con.createStatement();
} catch (ClassNotFoundException | SQLException ex) {
System.out.println("Error in constructor: " + ex);
}
}
//this method gets called before I make another query
public void reconnect() {
try {
st.close();
con.close();
if (con.isClosed()) {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname", "root", "");
st = con.createStatement();
}
} catch (SQLException ex) {
Logger.getLogger(SQLConnect.class.getName()).log(Level.SEVERE, null, ex);
}
}
//sample method on how I do queries
public ResultSet getMemberViaMemberId(String mID) {
try {
String query = "CALL getMemberViaMemberId(" + mID + ");"; //procedure call
rs = st.executeQuery(query);
} catch (Exception ex) {
System.out.println("Error: " + ex);
}
return rs;
}
}//end of class
The way I call it in my JForm is this..
SQLConnect connect;
public Class(){
connect = new SQLConnect();
}
public void methodThatGetsCalledALot(String current_id){
connect.reconnect(); //refer to SQLConnectClass displayed above
ResultSet member = connect.getMemberViaMemberId(current_id);
try{
if (member.next()) {
lastName = member.getString("last_name");
firstName = member.getString("first_name");
}
//display data...
} catch (SQLException ex){
}
}
The code:
connect.reconnect();
ResultSet rs = connect.callSQLMethod();
is the most essential bit and is called by every class, and by every method that needs to fetch data. I have to acknowledge that I never bother closing ResultSet because often times it's inside a loop and gets replaced with new data anyway.
Again, my problem is: I cant continue fetching data anymore because of too many connections. Am I really closing things properly or am I missing something? Any suggestions on how to fix this? If my question is too confusing, I'd add more details if required. Thank you. If anyone's to keen on freely helping me out, I'd go for some emailing. Thank you! And Happy New Year btw.
You seem to be creating a lot of connections and recursing with the ResultSet open. Don't create new connections all the time, all you need is one connection and don't reconnect all the time. You actually don't need the reconnect method at all (unless you connection closes automatically, in which case you can check if it is closed before executing query). And you need to close the ResultSet once you are done retrieving values.
All you need is the data and not the resultset. So take the data and release the resource ie ResultSet. So do this -
In your getMemberViaMemberId don't return ResultSet, in that method itself, iterate through the resultset and create the object for the row and store it into a collection and return that collection after closing the ResultSet. And dont call reconnect method at all.
Close the single connection that you have when exiting the program.
I am working on my first Java Project with MySQL. I have one function that gets called every time I get data back from my data source. This function should save a new line to my MySQL database. See the code here:
import java.sql.*;
import java.util.Properties;
/**
*
* #author jeffery
*/
public class SaveToMysql {
// The JDBC Connector Class.
private static final String dbClassName = "com.mysql.jdbc.Driver";
private static final String CONNECTION = "jdbc:mysql://localhost/test";
static public String test(int reqId, String date, double open, double high, double low,
double close, int volume, int count, double WAP, boolean hasGaps){
if (date.contains("finished")){
return "finished";
}
// Class.forName(xxx) loads the jdbc classes and
// creates a drivermanager class factory
try{
Class.forName(dbClassName);
}catch ( ClassNotFoundException e ) {
System.out.println(e);
}
// Properties for user and password. Here the user and password are both 'paulr'
Properties p = new Properties();
p.put("user","XXXXXXXX");
p.put("password","XXXXXXXXXXXx");
// Now try to connect
Connection conn;
try{
conn = DriverManager.getConnection(CONNECTION,p);
}catch(SQLException e){
return e.toString();
}
PreparedStatement stmt;
try{
stmt = conn.prepareStatement("insert into dj_minute_data set symbol = (select ticker from dow_jones_constituents where id = ?), "
+ "date = str_to_date(?,'%Y%m%d %H:%i:%s')" +
", open = ?" +
", high = ?" +
", low = ?" +
", close = ?" +
", volume = ?" +
", adj_close = ?");
stmt.setInt(1, reqId);
stmt.setString(2, date);
stmt.setDouble(3, open);
stmt.setDouble(4, high);
stmt.setDouble(5, low);
stmt.setDouble(6, close);
stmt.setDouble(7, volume);
stmt.setDouble(8, WAP);
}catch (SQLException e){
return e.toString();
}
try{
stmt.executeUpdate();
}catch (SQLException e){
return e.toString();
}
return stmt.toString();
}
}
As you all can see this function test is in its own class, called SaveToMysql. To call this function, I import the class into a different class, and use this syntax:
msg = SaveToMysql.test(reqId, date, open, high, low, close, volume, count, WAP, hasGaps);
The msg then get output to the screen. Showing either error message or success.
This function may be called many times rapidly in a short time period. I know I should not have to re-open my connection with the MySQL server every time the function gets called. How would I change this so that the 1 MySQL connection stays open for every call to the function.
Thanks!!
JDBC URL: jdbc:mysql://:/? connectTimeout=0&socketTimeout=0&autoReconnect=true
I know I should not have to re-open my connection with the MySQL server every time the function gets called.
No, it's fine to do so - as long as you have a connection pool under the hood to manage the real connections. There are various connection pool projects around, such as c3p0 and DBCP. That way you can make each of your calls isolated from the others:
Fetch a connection from the pool
Use it
Release it back to the pool
See the documentation for whichever pool you choose for the details. Often connection pools allow you to just request a connection from JDBC as normal and then close it as normal, effectively making the whole thing transparent.
Also note that you should definitely start using prepared statements with parameters rather than including your values directly in your SQL statement. Your current code is a SQL injection attack waiting to happen.
you need to manage one static class or method.
like
public class ConnectionClass
{
public static Connection connection = null;
public Connection getCurrentConnection()
{
if(connection != null)
{
return connection;
}
else
{
create new connection...
and return that new connection after giving it to global connection..
}
}
}
by this every time you will get current connection. and if there is some issue and connection is not available then you can create new connection. when you need connection object you just need to call getCurrentConnection method.
so you just need to following things in ur code.
Connection conn;
try{
//conn = DriverManager.getConnection(CONNECTION,p);
conn = getCurrentConnection();
}catch(SQLException e){
return e.toString();
}
If you want use 1 connection when call SaveToMysql.test method many times, you can add your connection in method parameter, or create a global connection variable out side SaveToMysql.test method. but, if you use 1 connection, please attention about transaction. I hope it will help you.