For university, it is my excercise to develop a multiplayer game with Java. The communication between the clients shall not be handled with sockets or the like, but with the help of a MySQL database where the clients are adding their steps in the game. Because it is a game of dice, not a lot of queries are needed. (approximiately 30 queries per gaming session are needed).
I never used MySQL in connection with Java before, so this maybe is a beginner's fault. But actually, I often get an exception during the execution of my java project.
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: User my_username already has more than 'max_user_connections' active connections
My queries are executed in a DatabaseHelper.java class. The results are returned and evaluated in another class of the project. Since I use an MVC pattern, I evaluate the results in a controller or model class.
This for example is one of my quers in the DatabaseHelper.java class. The other queries are similar:
private static Connection conn;
private Connection getConn() {
return conn;
}
public void db_connect() throws ClassNotFoundException, SQLException{
// JDBC Klassen laden
Class.forName(dbClassName);
// Verbindungsversuch auf 5 Sekunden setzen
DriverManager.setLoginTimeout(5);
this.setConn(DriverManager.getConnection(CONNECTION,p)); // p contains the username and the database
}
public void db_close(){
try {
this.getConn().close();
} catch (SQLException e) {
if(GLOBALVARS.DEBUG)
e.printStackTrace();
}
}
public String[] query_myHighscores(int gameid, PlayerModel p) throws SQLException{
List<String> rowValues = new ArrayList<String>();
PreparedStatement stmnt;
if(gameid == GLOBALVARS.DRAGRACE)
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score ASC LIMIT 0,3");
else
stmnt = this.getConn().prepareStatement("SELECT score FROM highscore WHERE gid = ? and pname = ? ORDER BY score DESC LIMIT 0,3");
stmnt.setInt(1, gameid);
stmnt.setString(2, p.getUname());
ResultSet rs = stmnt.executeQuery();
rs.beforeFirst();
while(rs.next()){
rowValues.add(rs.getString(1));
}
stmnt.close();
rs.close();
return (String[])rowValues.toArray(new String[rowValues.size()]);
}
The CONNECTION string is a string which looks like jdbc:mysql://my_server/my_database
In the HighscoreGUI.java class, I request the data like this:
private void actualizeHighscores(){
DatabaseHelper db = new DatabaseHelper();
try{
db.db_connect();
String[] myScoreDragrace = db.query_myHighscores(GLOBALVARS.GAME1); // id of the game as parameter
// using the string
} finally {
db.db_close();
}
So I tried:
Closing the statement and the ResultSet after each query
Used db_close() to close the connection to the dabase in the finally-block
Never returning a ResultSet (found out this may become a performance leak)
The stacktrace leads in the DatabaseHelper.java class to the line
this.setConn(DriverManager.getConnection(CONNECTION,p));
But I cannot find my mistake why I still get this exception.
I cannot change every settings for the database since this is a shared host. So I'd prefer a solution on Java side.
The problem is that you exceed your allowed set of connections to that database. Most likely this limit is exactly or very close to "1". So as soon as you request your second connection your program crashes.
You can solve this by using a connection pooling system like commons-dbcp.
That is the recommended way of doing it and the other solution below is only if you may not use external resources.
If you are prohibited in the external code that you might use with your solution you can do this:
Create a "Database" class. This class and only this class ever connects to the DB and it does so only once per program run. You set it up, it connects to the database and then all the queries are created and run through this class, in Java we call this construct a "singleton". It usually has a private constructor and a public static method that returns the one and only instance of itself. You keep this connection up through the entire livetime of your program and only reactivate it if it gets stall. Basically you implement a "Connection Pool" for the specific case of the pool size "1".
public class Database {
private static final Database INSTANCE = new Database();
private Database() {}
public static Database getInstance() {
return INSTANCE;
}
// add your methods here.
}
When the program terminates, close the Connection (using a shutdown hook).
Related
I am developing a program that, based on a configuration file, allows different types of databases (e.g., YAML, MySQL, SQLite, and others to be added in the future) to be used to store data.
Currently it is all running on the main thread but I would like to start delegating to secondary threads so as not to block the execution of the program.
For supported databases that use a connection, I use HikariCP so that the process is not slowed down too much by opening a new connection every time.
The main problem is the multitude of available databases. For example, for some databases it might be sufficient to store the query string in a queue and have an executor check it every X seconds; if it is not empty it executes all the queries. For others, however, it is not, because perhaps they require other operations (e.g., YAML files that use a key-value system with a map).
What I can't do is something "universal", that doesn't give problems with the order of queries (cannot just create a Thread and execute it, because then one fetch thread might execute before another insertion thread and the data might not be up to date) and that can return data on completion (in the case of get functions).
I currently have an abstract Database class that contains all the get() and set(...) methods for the various data to be stored. Some methods need to be executed synchronously (must be blocking) while others can and should be executed asynchronously.
Example:
public abstract class Database {
public abstract boolean hasPlayedBefore(#Nonnull final UUID uuid);
}
public final class YAMLDatabase extends Database {
#Override
public boolean hasPlayedBefore(#Nonnull final UUID uuid) { return getFile(uuid).exists(); }
}
public final class MySQLDatabase extends Database {
#Override
public boolean hasPlayedBefore(#Nonnull final UUID uuid) {
try (
final Connection conn = getConnection(); // Get a connection from the poll
final PreparedStatement statement = conn.prepareStatement("SELECT * FROM " + TABLE_NAME + " WHERE UUID= '" + uuid + "';");
final ResultSet result = statement.executeQuery()
) {
return result.isBeforeFirst();
} catch (final SQLException e) {
// Notifies the error
Util.sendMessage("Database error: " + e.getMessage() + ".");
writeLog(e, uuid, "attempt to check whether the user is new or has played before");
}
return true;
}
}
// Simple example class that uses the database
public final class Usage {
private final Database db;
public Usage(#Nonnull final Database db) { this.db = db; }
public User getUser(#Nonnull final UUID uuid) {
if(db.hasPlayedBefore(uuid))
return db.getUser(uuid); // Sync query
else {
// Set default starting balance
final User user = new User(uuid, startingBalance);
db.setBalance(uuid, startingBalance); // Example of sync query that I would like to be async
return user;
}
}
}
Any advice? I am already somewhat familiar with Future, CompletableFuture and Callback.
Have an application running and user can select normal backup or automatic backup of database.
Everything is running good except one thing...
If user wants to restore from backup database
How could I achieve that?
For example
if(a){Connection conn = DriverManager.getConnection("jdbc:derby:dbER;create=true");}
else{"jdbc:derby:dbER;restoreFrom=PATH");}
What could be "a" as a decision maker?
public class ConnectDatabase {
private static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
private static final String JDBC_URL = "jdbc:derby:dbER;create=true";
//private static final String JDBC_URL = "jdbc:derby:dbER;restoreFrom=/Applications/ER/dbER";
//static private Connection conn;
static Connection conn;
static private PreparedStatement preparedStatement;
prepareInsert PI = new prepareInsert();
public ConnectDatabase() {
try {
conn = DriverManager.getConnection(JDBC_URL);
if (conn != null){
//System.out.println("Connedted to database");
}
} catch (SQLException ex) {
Logger.getLogger(ConnectDatabase.class.getName()).log(Level.SEVERE, null, ex);
}
}
I'd be wary of automating a restore of your database from a backup. Restoring your database from a backup seems like an infrequent, unusual, special scenario.
Note that, among other things, it's quite a destructive operation, because you lose all the data in your current database, it gets replaced by the data from the backup!
I think that a sophisticated user of your program might be able to decide that they wanted to perform such a restore, but I think it's best to ensure that it will be a human making that decision, you should not try to encode it as an algorithm that makes that decision for the human.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm developing a java based application using NetBeans. My app opens with a window with asks the user to enter their credentials and based on data entered, a connection is established between the app and my MySQL client (I'm using JDBC for this purpose).
My issue: I want the connection object (which is declared and initialized after checking the credentials of the user) to be available for use in all my form. Previously, i have being doing this by passing the connection object from one form to another. But i don't want to do that! I want once this connection object is declared, it's made available to all the forms in the app.
I want the connection object (...) to be available for use in all my form
You should not have an open connection while your application lives. Instead, use a database connection pool of 1 or 2 connections that will be available for all the application and add a shutdown hook to close this data source when the application finishes. The connection pool will take care to maintain the connections alive and use low resources for it.
For example: your user opens the application and enters its credentials, then leaves the room because he/she has to do some paperwork and takes 30 mins, then goes back to the pc and try to use an option. If using a static Connection con object, you manually opened a physical connection to the database and you're in charge to control the connectivity for all these 30 minutes, and if you don't do any action in that time then probably the physical connection was closed by the database engine. If using a connection pool, this will take care of opening/closing physical connections and maintaining them in sleep state so your connection won't be lost.
Note that your Connection object and related resources (PreparedStatement, ResultSet, etc). should be in the narrowest possible scope.
Here's a minimal example of doing this using BoneCP as database connection pool.
public class ConnectionProvider {
private static DataSource dataSource;
private static boolean initialized = false;
public static void init(Map<String, String> conf) {
if (!initialized) {
//synchronization to avoid multiple threads accesing to this part of the method
//at the "same time"
synchronized(DataSourceProvider.class) {
//double validation in case of multi threaded applications
if (!initialized) {
//you may add more validations here
//in case you want to use another datasource provider
//like C3PO, just change this part of the code
BoneCPDataSource bds = new BoneCPDataSource();
bds.setDriverClass(conf.get("driver"));
bds.setJdbcUrl(conf.get("url"));
bds.setUsername(conf.get("user"));
bds.setPassword(conf.get("password"));
//this should be obtained as configuration parameter
bds.setMaxConnectionsPerPartition(2);
//you can add more BoneCP specific database configurations
dataSource = bds;
initialized = true;
}
}
}
}
public static Connection getConnection() {
if (dataSource == null) {
//this should be a custom exception in your app
throw new RuntimeException("Data Source was not initialized.");
}
return dataSource.getConnection();
}
}
And the client (once you have called the init method and provided the database configurations). I'm avoiding exception handling for brevity:
public class SomeDao {
private Connection con;
//using Dependency Injection by composition for DAO classes with connection
public SomeDao(Connection con) {
this.con = con;
}
public SomeEntity getSomeEntity(int id) {
String sql = "SELECT id, col1, col2 FROM someEntity WHERE id = ?";
//PreparedStatement and ResultSet go on the narrowest possible scope
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
SomeEntity someEntity = new SomeEntity();
if (rs.hasNext()) {
someEntity.setId(rs.getInt("id");
//similar for other columns...
}
//don't forget to close the resources after its usage
return someEntity;
}
}
public class SomeService {
public SomeEntity getSomeEntity(int id) {
//retrieving the connection at this level
//a service may access to several daos
Connection con = ConnectionProvider.getConnection();
//performing the operations against DAO layer
SomeDao someDao = new SomeDao(con);
SomeEntity someEntity = someDao.getSomeEntity(id);
//closing the connection. This is A MUST
//here the connection pool won't close the physical connection
//instead put it to sleep
con.close();
//return the proper data at a single point of the method
return someEntity;
}
}
Don't use the same Connection in your application! But what you want to achieve could be done using static variable. For example, add the following code to any of your classes, or create a new class for it:
private static Connection con = null;
public static Connection getConnection (String url)
{
if (con == null)
con = DriverManager.getConnection(url);
return con;
}
Then, call MyClass.getConnection("jdbc:mysql://localhost:3306/") or whatever the connection string is, and it will return one Connection that you could use for all classes.
First i show you the code then asked few questions. i have a class database connectivity like this (please ignore syntax error if any)
class DatabaseConnection {
private static Connection connection = null;
private static String driverName="";
private static String userName="";
private static String passwrod="";
private static String url="";
private DatabaseConnection() { }
public static void createConnection() {
if ( connection == null ) {
// read database credentials from xml file and set values of driverName, userName, passowrd and url
//create connection with database and set store this connection in connection object created a class level.
}
}
public static void closeConnection1() throws Exception{
if ( connection != null ) {
connection.close();
connection == null
}
}
public static void closeConnection2() throws Exception{
if ( connection != null ) {
connection.close();
}
}
public void insertData(Object data) {
// insetData in database
}
}
I want to know which close connection is more optimize in database connection. Lets suppose I have test class like this
class Test {
public static void main(String args[]) {
DatabaseConnection.createConnection();
DatabaseConnection.insertData(data);
DatabaseConnection.closeConnection2(); // we call also called close connection method within the insertData method after inserting the data
}
}
After creating database connection i insert data in database and then close the connection using closeConnection2 method. in this way connection has been close so if i want to insert some more method then i have to recreate connection with the database but i can't do this because connection object is not null and createConnection didn't execute the code inside the if statement. Now if I called closeConnection1 method for closing connection then in doing this i have to parse xml file again for credential which is not a optimize solution. can you tell me which method is good and if both are worse then please tell me more efficient way for creating and closing database connection.
I see two major problems with this:
The fact that everything (including the Connection object) is static means that you can't ever use this class from more than one thread at once.
parsing the configuration data and opening the connection are separate concerns and should not be mixed. At least move them into separate methods, the configuration could probably even go in another class.
The second thing alone will avoid having to parse the connection information multiple times.
An even better approach would be to use a DataSource instead of opening the connections each time. And then use a DataSource that's actually a connection pool!
I'm trying to generate some sql files in my java application.
The application will not execute any sql statements, just generate a file with sql statements and save it.
I'd like to use the java.sql.PreparedStatement to create my statements so that i don't have to validate every string etc. with my own methods.
Is there a way to use the PreparedStatement without the calling java.sql.Connection.prepareStatement(String) function, because I don't have a java.sql.Connection?
Take a look at this Java library: http://openhms.sourceforge.net/sqlbuilder/
I'm guessing that until you've got a sql connection, the parser won't know what rules to apply. I'm guessing that it's actually the SQL driver or even server that's compiling the sql statement.
Assuming your sql is simple enough, then how about using a cheap connection, like, say a sqlite connection.
SQLite will create a new database on the fly if the database you're attempting to connect to does not exist.
public Connection connectToDatabase() {
// connect to the database (creates new if not found)
try {
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection("jdbc:sqlite:mydatabase.db");
// initialise the tables if necessary
this.createDatabase(conn);
}
catch (java.lang.ClassNotFoundException e) {
System.out.println(e.getMessage());
}
catch (java.sql.SQLException e) {
System.out.println(e.getMessage());
}
return conn;
}
Not really. Preparing a statement in most cases means that it will be compiled by DBMS which is "hard" without connection.
http://java.sun.com/docs/books/tutorial/jdbc/basics/prepared.html
This is a dastardly devious problem, thankfully it's pretty easy to cope with:
public class PreparedStatementBuilder
{
private String sql; // the sql to be executed
public PreparedStatementBuilder(final String sql) { this.sql = sql; }
protected void preparePrepared(final PreparedStatement preparedStatement)
throws SQLException
{
// this virtual method lets us declare how, when we do generate our
// PreparedStatement, we want it to be setup.
// note that at the time this method is overridden, the
// PreparedStatement has not yet been created.
}
public PreparedStatement build(final Connection conn)
throws SQLException
{
// fetch the PreparedStatement
final PreparedStatement returnable = conn.prepareStatement(sql);
// perform our setup directives
preparePrepared(returnable);
return returnable;
}
}
To use, just write an anonymous class that overrides void preparePrepared(PreparedStatement):
final String sql = "SELECT * FROM FOO WHERE USER = ?";
PreparedStatementBuilder psBuilder = new PreparedStatementBuilder(sql){
#Override
protected void preparePrepared(PreparedStatement preparedStatement)
throws SQLException
{
preparedStatement.setString(1, "randal");
}};
return obtainResultSet(psBuilder);
Presto! You now have a way to work with a PreparedStatement without yet having built it. Here's an example showing the minimal boilerplate you'd otherwise have to copy paste to kingdom come, every time you wanted to write a different statement:
public ResultSet obtainResultSet(final PreparedStatementBuilder builder)
throws SQLException {
final Connection conn = this.connectionSource.getConnection();
try
{
// your "virtual" preparePrepared is called here, doing the work
// you've laid out for your PreparedStatement now that it's time
// to actually build it.
return builder.build(conn).executeQuery();
}
finally
{
try { conn.close(); }
catch (SQLException e) { log.error("f7u12!", e); }
}
}
You really really don't want to be copy pasting that everywhere, do you?
Try implementing PreparedStatement.
Example : class YourOwnClass implements PreparedStatement {
// 1. Do implement all the methods ,
2. Get the minimal logic to implement from OraclePreparedStatement(classes12.jar) or
sun.jdbc.odbc.JdbcOdbcCallableStatement
}