I have the following class:
public class Database {
private Connection connection;
private MyApp instance = MyApp.getInstance();
private String database, host, username, password, port;
private Config config = new Config();
public Connection Database() {
database = config.get("database.database");
host = config.get("database.host");
username = config.get("database.username");
password = config.get("database.password");
port = config.get("database.port");
try {
connection = openConnection();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return connection;
}
private Connection openConnection() throws SQLException, ClassNotFoundException {
if (connection != null && !connection.isClosed()) {
}
synchronized (instance) {
if (connection != null && !connection.isClosed()) {
}
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database, username, password);
}
return connection;
}
}
I'd like to be able to return connection on this class so I can, in other classes, do connection = new Database(). and then Statement statement = connection.createStatement();.
This probably and feels like this isn't the best way, and I'm not sure what is a better way of creating a database class. My attempt was trying to do return connection; in the constructor but that error'd out.
How do I do this?
You can try something like this :
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Baza {
private static java.sql.Connection conect = null;
private static final String url = "jdbc:mysql://localhost/Application?autoReconnect=true&useSSL=false";
private static final String username = "root";
private static final String password = "";
private final String urlWithoutBase= "jdbc:mysql://localhost:3306/";
public Baza() {
try {
conect = DriverManager.getConnection(urlWithoutBase, username, password);
createDataBase();
conect.close();
openConnection();
createTablePeople();
conect.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public Connection openConnection() {
try {
conect = DriverManager.getConnection(url, username, password);
return conect;
} catch (SQLException ex) {
ex.printStackTrace();
}
return conect;
}
public void closeConnection() {
try {
conect.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
private void createDataBase() throws SQLException {
Statement statement = conect.createStatement();
String query = "CREATE DATABASE IF NOT EXISTS Application;";
statement.execute(query);
}
private void createTablePeople() throws SQLException{
Statement statement = conect.createStatement();
String query = "CREATE TABLE IF NOT EXISTS Osobe("
+ "id INT NOT NULL AUTO_INCREMENT,"
+ "name VARCHAR(30) NOT NULL,"
+ "surname VARCHAR(30) NOT NULL,"
+ "date VARCHAR(30) NOT NULL,"
+ "PRIMARY KEY(id));";
statement.execute(query);
}
}
Related
To get an idea of what the basic structure looks like, I downloaded a money system including MySQL from Spigot and looked at the code.
public static boolean playerExists(String uuid) {
try {
ResultSet rs = Simplecoinsystem.mysql.query("SELECT * FROM CoinData WHERE UUID= '" + uuid + "'");
if (rs.next())
return (rs.getString("UUID") != null);
return false;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public static void createPlayer(String uuid) {
if (!playerExists(uuid))
Simplecoinsystem.mysql.update("INSERT INTO CoinData (UUID, COINS) VALUES ('" + uuid +
"', '" + Simplecoinsystem.getInstance().getConfig().getInt("startcoins") + "');");
}
public static Integer getCoins(String uuid) {
Integer i = Integer.valueOf(0);
if (playerExists(uuid)) {
try {
ResultSet rs = Simplecoinsystem.mysql.query("SELECT * FROM CoinData WHERE UUID= '" + uuid + "'");
if (rs.next())
Integer.valueOf(rs.getInt("COINS"));
i = Integer.valueOf(rs.getInt("COINS"));
} catch (SQLException e) {
e.printStackTrace();
}
} else {
createPlayer(uuid);
}
return i;
}
public static void setCoins(String uuid, Integer coins) {
if (playerExists(uuid)) {
Simplecoinsystem.mysql.update("UPDATE CoinData SET COINS= '" + coins + "' WHERE UUID= '" + uuid + "';");
} else {
createPlayer(uuid);
}
}
Am I correct that it is actually impractical to create a new entry with the uuid of the non-existent player after each query of the coins if the player does not exist?
Wouldn't this make it possible to flood the database with thousands of unnecessary entries by issuing, for example, a "/money (player)" command as an evil player/admin?
Couldn't I just ask when entering the server if the uuid is already stored and if not, just enter it? This way there would only be entries from players who have already been on the server before. Whether this needs great server performance, I'm not sure.
This is my first own MySQL class.
public class MySQL {
private String host, database, user, password;
private int port;
private Connection con;
public MySQL(String host, int port, String database, String user, String password) {
this.host = host;
this.port = port;
this.database = database;
this.user = user;
this.password = password;
connect();
}
public void connect() {
try {
con = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoReconnect=true", user, password);
System.out.println("&cDie MySQL Verbindung wurde erfolgreich aufgebaut!");
} catch (SQLException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
if(this.con != null) {
this.con.close();
System.out.println("§cDie MySQL Verbindung wurde erfolgreich beendet!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void update(String query) {
try {
Statement st = con.createStatement();
st.executeUpdate(query);
st.close();
} catch (Exception e) {
e.printStackTrace();
connect();
}
}
public ResultSet qry(String query) {
ResultSet rs = null;
try {
Statement st = con.createStatement();
rs = st.executeQuery(query);
} catch (Exception e) {
e.printStackTrace();
connect();
}
return rs;
}
public Connection getConnection() {
return this.con;
}
}
Except for this part, both MySQL classes are built relatively the same.
This is the part that is in the MySQL class of the Spigot plugin.
Your code have multiple issues.
When the connection will be closed, next time you will have an error. In your Mysql class, I suggest you to do:
public Connection getConnection() {
if(con == null || con.isClosed())
connect();
return con;
}
Then, use it in all method like getConnection().prepareStatement().
You can be attacked with SQL Injection. To fix this, try to do something like:
PreparedStatement st = con.prepareStatement("SELECT * FROM CoinData WHERE UUID = ?");
st.setString(1, uuid.toString()); // Yes it start at 1 !!
st.executeUpdate();
With this, even with all values, you can't be attacked with injections.
You will have an error while getting coins:
if (rs.next()) // go to good line
Integer.valueOf(rs.getInt("COINS")); // useless convertion
i = Integer.valueOf(rs.getInt("COINS")); // error if no line.
You can just do:
if(rs.next())
i = rs.getInt("COINS");
If the column "UUID" is unique, you will not have duplicated lines.
Finally, about performance, it's better to do it one time: at login, instead of all time. You can also create an object stored in an hashmap to easier access to it, without using SQL, like that:
public static HashMap<UUID, Integer> coinsByPlayer = new HashMap<>();
OR:
public static HashMap<UUID, MyObject> coinsByPlayer = new HashMap<>();
public class MyObject {
private int coins = 0;
public MyObject(UUID uuid) {
// make SQL request to get data
}
public int getCoins() {
return coins;
}
public void setCoins(int next){
coins = next;
// here make "UPDATE" sql query
}
}
What do you say? Is it ok with the try/catch function? #Elikill58
public Connection getConnection() {
try {
if(con == null || con.isClosed()) {
connect();
}
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
edit:
public Connection getConnection_one() throws SQLException {
if(con == null || con.isClosed()) {
connect();
return con;
} else {
return con;
}
}
I would like to ask how to make Connection con = getConnection(); becaome a primer or main variable so that it would not connect to SQL database every function made. Because as you can see on my codes, every function/class has Connection con = getConnection(); so it connects to the database every function. It makes my program process slowly. Please help thank you.
package march30;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
public class sqltesting {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
get();
}
public static void lookup() throws Exception{
try {
Connection con = getConnection();
PreparedStatement statement = con.prepareStatement("SELECT first,last FROM tablename where id=6");
ResultSet result = statement.executeQuery();
if (result.next()) {
System.out.println("First Name: " + result.getString("first"));
System.out.println("Last Name: " + result.getString("last"));
}
else {
System.out.println("No Data Found");
}
} catch (Exception e) {}
}
public static ArrayList<String> get() throws Exception{
try {
Connection con = getConnection();
PreparedStatement statement = con.prepareStatement("SELECT first,last FROM tablename");
ResultSet result = statement.executeQuery();
ArrayList<String> array = new ArrayList<String>();
while (result.next()) {
System.out.print(result.getString("first"));
System.out.print(" ");
System.out.println(result.getString("last"));
array.add(result.getString("last"));
}
System.out.println("All records have been selected!");
System.out.println(Arrays.asList(array));
return array;
} catch (Exception e) {System.out.println((e));}
return null;
}
public static void update() throws Exception{
final int idnum = 2;
final String var1 = "New";
final String var2 = "Name";
try {
Connection con = getConnection();
PreparedStatement updated = con.prepareStatement("update tablename set first=?, last=? where id=?");
updated.setString(1, var1);
updated.setString(2, var2);
updated.setInt(3, idnum);
updated.executeUpdate();
} catch (Exception e) {System.out.println((e));}
finally{
System.out.println("Update Completed");
}
}
public static void delete() throws Exception{
final int idnum = 7;
try {
Connection con = getConnection();
PreparedStatement deleted = con.prepareStatement("Delete from tablename where id=?");
deleted.setInt(1, idnum);
deleted.executeUpdate();
} catch (Exception e) {System.out.println((e));}
finally{
System.out.println("Delete Completed");
}
}
public static void post() throws Exception{
final String var1 = "Albert";
final String var2 = "Reyes";
try {
Connection con = getConnection();
PreparedStatement posted = con.prepareStatement("INSERT INTO tablename (first, last) VALUES ('"+var1+"', '"+var2+"')");
posted.executeUpdate();
} catch (Exception e) {System.out.println((e));}
finally{
System.out.println("Insert Completed");
}
}
public static void createTable() throws Exception {
try {
Connection con = getConnection();
PreparedStatement create = con.prepareStatement("CREATE TABLE IF NOT EXISTS tablename(id int NOT NULL AUTO_INCREMENT, first varchar(255), last varchar(255), PRIMARY KEY(id))");
create.executeUpdate();
} catch (Exception e) {System.out.println((e));}
finally{
System.out.println("Function Completed");
}
}
public static Connection getConnection() throws Exception{
try {
String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://xxxxxxxx.amazonaws.com:3306/pointofsale";
String username = "xxxxx";
String password = "xxxxxx";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url,username,password);
return conn;
} catch (Exception e) {System.out.println(e);}
return null;
}
}
To solve your problem you need to store a Connection object in your sqltesting class as a class member. You then need to reference the Connection object instead of getConnection(). It's also worth mentioning that Connection is a AutoClosable object so you need to close this resource when you're done with it, I.E; on application disposal. You also might want to consider using a connection pooling API like Hikari or C3P0 so you can open and close connections when you need them instead of having 1 open for a long time.
class SQLTesting {
private final Connection connection;
public SQLTesting(Connection connection) {
this.connection = connection;
}
public SQLTesting() {
this(getConnection());
}
// other methods
private Connection getConnection() {
// your method to create connection, rename to createConnection maybe.
}
}
I have problem about connecting through jdbc to my file-based hsqldb.
Here is my Dao class
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class EventDao {
private static final String URL = "jdbc:hsqldb:file:C:/Applications/CreditTask/db";
private static final String USER = "sa";
private static final String PASS = "";
private Connection connection;
public EventDao() {
try {
Class.forName("org.hsqldb.jdbc.JDBCDriver");
connection = DriverManager.getConnection(URL, USER, PASS);
dropAndCreateTable();
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
private void dropAndCreateTable() throws SQLException {
final String dropSql = "drop table event";
PreparedStatement preparedStatement = connection.prepareStatement(dropSql);
preparedStatement.execute();
final String createSql = "create table event(\n" +
" id int not null,\n" +
" state varchar(10) not null,\n" +
" timestamp int not null,\n" +
" type varchar(15),\n" +
" host varchar(15),\n" +
" alert boolean\n" +
")";
preparedStatement = connection.prepareStatement(createSql);
preparedStatement.execute();
}
public void save(Event event) {
final String sql = "insert into event(id,state,timestamp,type,host,alert) values (?,?,?,?,?,?)";
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, event.getId());
preparedStatement.setString(2, event.getState());
preparedStatement.setString(3, event.getTimestamp().toString());
preparedStatement.setString(4, event.getType());
preparedStatement.setString(5, event.getHost());
preparedStatement.setString(6, event.getAlert().toString());
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
And here is where i use it
public class EventParser {
private static final String FILE_NAME = "log.json";
private static final String STARTED = "STARTED";
private static final String FINISHED = "FINISHED";
private static final Long MAX_ALERT_RANGE = 4L;
private static final Logger logger
= LoggerFactory.getLogger(EventParser.class);
public static void main(String[] args) {
EventParser eventParser = new EventParser();
eventParser.runApp();
}
public void runApp() {
try {
EventDao eventDao = new EventDao();
logger.info("Reading events from file");
Map<String, EventWrapper> eventsFromFile = readEventsFromFile();
List<Event> eventsToSave = calculateEventTime(eventsFromFile);
//2h in this state i didn't test saving to db using eventDao
for (Event event : eventsToSave) {
Runnable runnable = () -> eventDao.save(event);
runnable.run();
}
eventDao.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//rest of the class are methods that giving me arrays of events
The problem is when i run this application im getting error:
java.lang.ClassNotFoundException: org.hsqldb.jdbc.JDBCDriver
at
java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:332)
at event.EventDao.<init>(EventDao.java:19)
at event.EventParser.runApp(EventParser.java:32)
at event.EventParser.main(EventParser.java:27)
I read documentation and i check if i have downloaded the library but everything seems to be ok. Have You got any ideas why im getting null in the connection? Also there is any improvment in this app that i would not need to use drop and create table everytime i run application through dao constructor?
When the call to Class.forName("org.hsqldb.jdbc.JDBCDriver") throws the exception, it means the hsqldb.jar is not included in your classpath when your java ... command is executed.
I have a program that queries a database using different jdbc drivers. This error is specific to the MySQL driver.
Here's the basic rundown.
I have another query runner class that uses a postgresql jdbc driver that works just fine. Note the line conn.close(); this works fine on my postgresql query runner, but for this SQL runner it comes up with the error.
I have removed the line conn.close(); and this code works fine, but over time it accumulates sleeping connections in the database. How can I fix this?
New Relic is a third party application that I am feeding data to, if you dont know what it is, don't worry it's not very relevant to this error.
MAIN CLASS
public class JavaPlugin {
public static void main(String[] args) {
try {
Runner runner = new Runner();
runner.add(new MonitorAgentFactory());
runner.setupAndRun(); // never returns
}
catch (ConfigurationException e) {
System.err.println("ERROR: " + e.getMessage());
System.exit(-1);
}
catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
System.exit(-1);
}
}
}
MYSQL QUERY RUNNER CLASS
import com.newrelic.metrics.publish.util.Logger;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;
public class MySQLQueryRunner {
private static final Logger logger = Logger.getLogger(MySQLQueryRunner.class);
private String connectionStr;
private String username;
private String password;
public MySQLQueryRunner(String host, long port, String database, String username, String password) {
this.connectionStr = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false";
this.username = username;
this.password = password;
}
private void logError(String message) {
logger.error(new Object[]{message});
}
private void logDebugger(String message) {
logger.debug(new Object[]{message});
}
private Connection establishConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
logError("MySQL Driver could not be found");
e.printStackTrace();
return null;
}
Connection connection = null;
try {
connection = DriverManager.getConnection(connectionStr, username, password);
logDebugger("Connection established: " + connectionStr + " using " + username);
} catch (SQLException e) {
logError("Connection Failed! Check output console");
e.printStackTrace();
return null;
}
return connection;
}
public ResultSet run(String query) {
Connection conn = establishConnection();
if (conn == null) {
logError("Connection could not be established");
return null;
}
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
conn.close();
return rs;
} catch (SQLException e) {
logError("Failed to collect data from database");
e.printStackTrace();
return null;
}
}
}
AGENT CLASS
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import com.newrelic.metrics.publish.Agent;
public class LocalAgent extends Agent {
private MySQLQueryRunner queryRunner;
private String name;
private Map<String, Object> thresholds;
private int intervalDuration;
private int intervalCount;
public LocalAgent(String name, String host, long port, String database, String username, String password, Map<String, Object> thresholds, int intervalDuration) {
super("com.mbt.local", "1.0.0");
this.name = name;
this.queryRunner = new MySQLQueryRunner(host, port, database, username, password);
// this.eventPusher = new NewRelicEvent();
this.thresholds = thresholds;
this.intervalDuration = intervalDuration;
this.intervalCount = 0;
}
/**
* Description of query
*/
private void eventTestOne() {
String query = "select count(1) as jerky from information_schema.tables;";
ResultSet rs = queryRunner.run(query);
try {
while (rs.next()) {
NewRelicEvent event = new NewRelicEvent("localTestOne");
event.add("jerky", rs.getInt("jerky"));
event.push();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* blah
*/
private void eventTestTwo() {
String query = "SELECT maxlen FROM information_schema.CHARACTER_SETS;";
ResultSet rs = queryRunner.run(query);
try {
while (rs.next()) {
NewRelicEvent event = new NewRelicEvent("localTestTwo");
event.add("beef", rs.getString("maxlen"));
event.push();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
#Override
public void pollCycle() {
if (this.intervalCount % this.intervalDuration == 0) {
eventTestOne();
eventTestTwo();
this.intervalCount = 0;
}
// Always incrementing intervalCount, keeping track of poll cycles that have passed
this.intervalCount++;
}
#Override
public String getAgentName() {
return this.name;
}
}
The problem is that you are trying to access the ResultSet after the connection is closed.
You should open and close the connection in the method that is calling run() this way the connection will be open when you access and loop through the Resultset and close it in the finally block of the calling method.
Even better would be if you can just loop through the ResultSet in the run() method and add the data to an object and return the object, this way you can close it in the finally block of the run() method.
I'm making some database tables using jdbc. On one of the tables I get this error message : TYPE 'MEET' does not exist.. Any ideas why?
The code is below:
public class MeetingDAO {
public static String getTableString(){
String meetingTable = "create table project ( " +
"meeting_id integer not null, " +
"timestamp meet, " +
"project_key varchar(10), " +
"primary key(meeting_id))";
return projectTable;
}
}
public class JDBCUtil {
private static final String dbURL= "jdbc:derby:MyDB;create=true;";
private static final String userID = "moon";
private static final String password = "moonmoon";
public static void init(){
makeTable(MeetingDAO.getTableString());
}
private static void makeTable(String tableSQL){
Connection conn = null;
try {
conn = JDBCUtil.getConnection();
Statement stmt = null;
try {
stmt = conn.createStatement();
stmt.executeUpdate(tableSQL);
}
finally {
JDBCUtil.closeStatement(stmt);
}
JDBCUtil.commit(conn);
}
catch (SQLException e) {
System.out.println(e.getMessage());
JDBCUtil.rollback(conn);
}
finally {
JDBCUtil.closeConnection(conn);
}
}
public static Connection getConnection() throws SQLException{
Driver derbyEmbededDriver = new EmbeddedDriver();
DriverManager.registerDriver(derbyEmbededDriver);
Connection conn = DriverManager.getConnection(dbURL, userID, password);
conn.setAutoCommit(false);
return conn;
}
public static void closeConnection(Connection conn){
try{
if(conn != null)
conn.close();
}
catch(SQLException e){
e.printStackTrace();
}
}
public static void closeStatement(Statement stmt){
try {
if(stmt != null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void closeResultSet(ResultSet rs){
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void commit(Connection conn){
try {
if(conn != null)
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback (Connection conn){
try {
if(conn != null)
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
just swap these two words:
timestamp meet
to
meet timestamp
first there comes the column naming, after that the column datatyp.
You mixed up column name and data type for the column meet.
public class MeetingDAO {
public static String getTableString(){
String meetingTable = "create table project ( " +
"meeting_id integer not null, " +
"meet timestamp, " +
"project_key varchar(10), " +
"primary key(meeting_id))";
return projectTable;
}
}