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.
Related
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 wrote stored procedure in MySQL which looks like this (it works):
DELIMITER //
CREATE PROCEDURE getBrandRows(
IN pBrand VARCHAR(30),
OUT pName VARCHAR(150),
OUT pType VARCHAR(200),
OUT pRetailPrice FLOAT)
BEGIN
SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
FROM part
WHERE p_brand LIKE pBrand;
END//
DELIMITER ;
I try to return multiple results and display them. I've tried many ways described here on Stack and in Internet but that does not help me. I have edited my entire code and created a simple one so you can guys paste it and compile. It should work but with error. Here is the code:
package javamysqlstoredprocedures;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JavaMySqlStoredProcedures {
private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/"
+ "anton869_cars?noAccessToProcedureBodies=true";
private final String DB_USER = "xxx";
private final String DB_PASSWORD = "xxx";
class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {
#Override
public Void doInBackground() {
displaySql();
return null;
}
#Override
public void done() {
}
private void displaySql() {
try {
System.out.println("Connecting to MySQL database...");
Class.forName(DEFAULT_DRIVER);
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER,
DB_PASSWORD)) {
System.out.println("Connected to MySQL database");
CallableStatement cs = conn.prepareCall("{CALL getBrandRows("
+ "?, ?, ?, ?)}");
cs.setString(1, "Brand#13");
cs.registerOutParameter(2, Types.VARCHAR);
cs.registerOutParameter(3, Types.VARCHAR);
cs.registerOutParameter(4, Types.FLOAT);
boolean results = cs.execute();
while (results) {
ResultSet rs = cs.getResultSet();
while (rs.next()) {
System.out.println("p_name=" + rs.getString("p_name"));
System.out.println("p_type=" + rs.getString("p_type"));
System.out.println("p_retailprice=" + rs
.getFloat("p_retailprice"));
}
rs.close();
results = cs.getMoreResults();
}
cs.close();
} catch (SQLException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public JavaMySqlStoredProcedures() {
new CallStoredProcedureAndSaveXmlFile().execute();
}
public static void main(String[] args) {
JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
}
}
ResultSet can handle multiple records.I found some errors in your code.Try these steps
Move your all close method to finally block.
try {
//do something
} catch (Exception e) {
//do something
} finally {
try{
resultSet.close();
statement.close();
connection.close();
} catch (SQLException se) {
//do something
}
}
You can put your result into List. See sample
List<YourObject> list = new ArrayList<YourObject>();
while (rs.next()) {
YourObject obj = new Your Object();
obj.setName(rs.getString("p_name"));
obj.setType(rs.getString("p_type"));
obj.setRetailPrice(rs.getFloat("p_retailprice"));
list.add(obj);
}
Make sure your query is correct and database connection is Ok.
Don't use IN or OUT parameter if you just simply want to display result. And also you should add '%%' in your LIKE clause with the help of CONCAT function. Please try this one:
DELIMITER //
CREATE PROCEDURE getBrandRows(
pBrand VARCHAR(30)
)
BEGIN
SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
FROM part
WHERE p_brand LIKE CONCAT("%", pBrand, "%");
END//
DELIMITER ;
I am posting correct solution to everybody who have smiliar problem:
1. Corrected Stored Procedure:
DELIMITER //
CREATE PROCEDURE getBrandRows(
IN pBrand VARCHAR(30))
BEGIN
SELECT p_name, p_type, p_retailprice
FROM part
WHERE p_brand = pBrand;
END//
DELIMITER ;
2. Corrected Java code:
package javamysqlstoredprocedures;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class JavaMySqlStoredProcedures {
private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/"
+ "anton869_cars?noAccessToProcedureBodies=true";
private final String DB_USER = "xxx";
private final String DB_PASSWORD = "xxx";
class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {
#Override
public Void doInBackground() {
displaySql();
return null;
}
#Override
public void done() {
}
private void displaySql() {
Connection conn = null;
CallableStatement cs = null;
ResultSet rs = null;
try {
System.out.println("Connecting to MySQL database...");
Class.forName(DEFAULT_DRIVER);
conn = DriverManager.getConnection(DB_URL, DB_USER,
DB_PASSWORD);
System.out.println("Connected to MySQL database");
cs = conn.prepareCall("{CALL getBrandRows(?)}");
cs.setString(1, "Brand#13");
boolean results = cs.execute();
while (results) {
rs = cs.getResultSet();
while (rs.next()) {
System.out.println("p_name=" + rs.getString("p_name"));
System.out.println("p_type=" + rs.getString("p_type"));
System.out.println("p_retailprice=" + rs.getFloat(
"p_retailprice"));
}
results = cs.getMoreResults();
}
} catch (SQLException | ClassNotFoundException e) {
} finally {
try {
if (rs != null ) rs.close();
if (cs != null) cs.close();
if (conn != null) conn.close();
} catch (SQLException e) {
}
}
}
public JavaMySqlStoredProcedures() {
new CallStoredProcedureAndSaveXmlFile().execute();
}
public static void main(String[] args) {
JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
}
}
Your stored procedure returns more than one row. Just correct logic behind your select query inside the stored procedure it should return only one row.
here how to return multiple value
I'm try to send the parameters from servlet to db and I get errors in my connection.
Steps of my works:
In eclipse I create a Dynamic Web Project with Tomcat server
Create a model (without any technology as a Spring , Hibernate, JSP, JSF and so on. ) for to use with DML methodology (clearing java code).
I tested the created module (by using some main test class) and it works so good (connections , inserting, deleting..).
After that , I can a simple HTML doc for client side.
process for running a web module step by step:
Before start Web project I start to run Derby DB - works OK.
Starting a Web project with Apache Tomcat.
insert data to the HTML and submitted it. - works OK
In the Servlet class the data gated to the doGet(...) method. - works OK.
From the Servlet (doGet(...) method) when I try to send the parameter to the DB I get errors in my conector class.
How can I set right that?
Thanks.
Codes:
Servlet Class:
#WebServlet({ "/StudentServlet", "/Student" })
public class StudentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private StudentDbDao sf = new StudentDbDao();
private Student student = new Student();
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter writer = response.getWriter();
String studentId = request.getParameter("sudentId");
Long id = Long.parseLong(studentId);
String studentFullName = request.getParameter("studentFullName");
String studentGendre = request.getParameter("studentGendre");
String studentGrade = request.getParameter("studentGrade");
try {
student.setId(id);
student.setFullName(studentFullName);
student.setGender(studentGendre);
student.setGrade(studentGrade);
sf.createStudent(student);
writer.println("The student #" + id + " inserted.");
} catch (StudentSystemException e) {
e.printStackTrace();
}
}
}
class StudentDbDao that response for DML functionality:
package dao.Db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import bean.Student;
import bean.StudentSystemException;
import dao.StudentDao;
import dao.connector.ConnectionPool;
public class StudentDbDao implements StudentDao {
private Connection conn;
public StudentDbDao() {
}
#Override
public void createStudent(Student student) throws StudentSystemException {
conn = ConnectionPool.getInstance().getConnection();
String sql = "INSERT INTO Students(ID, FULLNAME, GENDER, GRADE) VALUES(?, ?, ?, ?)";
PreparedStatement pstmt;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, student.getId());
pstmt.setString(2, student.getFullName());
pstmt.setString(3, student.getGender());
pstmt.setString(4, student.getGrade());
pstmt.executeUpdate();
System.out.println(student.getFullName() + " created successfully");
} catch (SQLException e) {
throw new StudentSystemException("Failed!", e);
} finally {
ConnectionPool.getInstance().returnConnection(conn);
}
}
#Override
public void removeStudent(Student student) throws StudentSystemException {
conn = ConnectionPool.getInstance().getConnection();
String sql = "DELETE FROM Students WHERE ID = " + student.getId();
PreparedStatement pstmt;
try {
pstmt = conn.prepareStatement(sql);
pstmt.executeUpdate();
System.out.println(student.getId() + " removed successfully.");
} catch (SQLException e) {
throw new StudentSystemException("Failed!", e);
} finally {
ConnectionPool.getInstance().returnConnection(conn);
}
}
#Override
public Student getStudentById(long id) throws StudentSystemException {
conn = ConnectionPool.getInstance().getConnection();
String sql = "SELECT * FROM Students WHERE ID = " + id;
Student student = new Student();
PreparedStatement pstmt;
ResultSet rs;
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if (rs.next()) {
student.setId(rs.getLong(1));
student.setFullName(rs.getString(2));
student.setGender(rs.getString(3));
student.setGrade(rs.getString(4));
}
// else {
// System.out.print("Student with PID #" + id + " not exists. ");
// }
return student;
} catch (SQLException e) {
throw new StudentSystemException("Failed!", e);
} finally {
ConnectionPool.getInstance().returnConnection(conn);
}
}
public long getMaxRows() throws StudentSystemException {
conn = ConnectionPool.getInstance().getConnection();
String sql = "SELECT COUNT(*) FROM Students";
PreparedStatement pstmt;
int count = 0;
try {
pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
rs.next();
count = rs.getInt(1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
ConnectionPool.getInstance().returnConnection(conn);
}
return count;
}
}
class ConnectionPool where code is falls when Servlet try to set the parameters:
public class ConnectionPool {
// static final int MAX_CONS = 1;
private Connection myconn = null;
// private Set<Connection> connections = new HashSet<Connection>();
private static ConnectionPool instance = new ConnectionPool();
String url = "jdbc:derby://localhost:1527/StudentDB";
private ConnectionPool() {
try {
myconn = DriverManager.getConnection(url);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static ConnectionPool getInstance() {
return instance;
}
public Connection getConnection() {
// Connection conn = myconn;
return this.myconn;
}
public void returnConnection(Connection conn) {
this.myconn = conn;
// myconn.add(conn);
}
public void closeAllConnections() throws StudentSystemException {
Connection connection = myconn;
try {
connection.close();
} catch (SQLException e) {
throw new StudentSystemException("Failed to close connection: ", e);
}
}
attached before submit and after print-screens:
before:
after:
So I'm quite new to Java and Derby. I'm using both with my Flex app on Tomcat 7.
When I make a call to Java from Flex the login function works fine but my getUserByUsername function does not.
public Boolean loginUser(String username, String password) throws Exception
{
Connection c = null;
String hashedPassword = new String();
try
{
c = ConnectionHelper.getConnection();
PreparedStatement ps = c.prepareStatement("SELECT password FROM users WHERE username=?");
ps.setString(1, username);
ResultSet rs = ps.executeQuery();
if(rs.next())
{
hashedPassword = rs.getString("password");
}
else
{
return false;
}
if(Password.check(password, hashedPassword))
{
return true;
}
else
{
return false;
}
}
catch (SQLException e)
{
e.printStackTrace();throw new DAOException(e);
}
finally
{
ConnectionHelper.closeConnection(c);
}
}
public User getUserByUsername(String username) throws DAOException
{
//System.out.println("Executing DAO.getUserByName:" + username);
User user = new User();
Connection c = null;
try
{
c = ConnectionHelper.getConnection();
PreparedStatement ps = c.prepareStatement("SELECT * FROM users WHERE username = ?");
ps.setString(1, username);
ResultSet rs = ps.executeQuery();
while(rs.next())
{
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setTeam(rs.getString("team"));
user.setScore(rs.getInt("score"));
}
}
catch (SQLException e)
{
e.printStackTrace();
throw new DAOException(e);
}
finally
{
ConnectionHelper.closeConnection(c);
}
return user;
}
The stack I get in Flex is useless as far as I can tell:
Flex Message (flex.messaging.messages.ErrorMessage) clientId = 8EB6D37B-7E0B-01B0->AA55-457722B9036C correlationId = A39E574F-CFC6-51FE-6CBE-451AF329E2F8 destination >= service messageId = 8EB6DF4C-650B-BDD7-7802-B813A61C8DC8 timestamp = >1401318734645 timeToLive = 0 body = null code = Server.Processing message = >services.DAOException : java.sql.SQLException: Failed to start database >'/Applications/blazeds/tomcat/webapps/testdrive/WEB-INF/database/game_db', see the next >exception for details. details = null rootCause = ASObject(23393258)>>{message=java.sql.SQLException: Failed to start database >'/Applications/blazeds/tomcat/webapps/testdrive/WEB-INF/database/game_db', see the next >exception for details., suppressed=[], localizedMessage=java.sql.SQLException: Failed to >start database '/Applications/blazeds/tomcat/webapps/testdrive/WEB->INF/database/game_db', see the next exception for details., cause=java.sql.SQLException} >body = null extendedData = null
My first thought was that it was just an error in my function (maybe someone else will notice it) but I've been looking through it for a couple hours and I can't see anything.
After that I thought maybe Derby had a problem with concurrent connections. I saw somewhere that Embedded JDBC can only handle one connection so I changed the driver from Embedded to Client which once again resulted in the login function working and the other an error saying the url in the connection was null. Any thoughts? Thanks ahead of time for any ideas.
EDIT:
package services;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.net.URLDecoder;
public class ConnectionHelper
{
private String url;
private static ConnectionHelper instance;
public String getUrl()
{
return url;
}
private ConnectionHelper()
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
String str = URLDecoder.decode(getClass().getClassLoader().getResource("services").toString(),"UTF-8");
str= str.substring(0, str.indexOf("classes/services"));
if ( str.startsWith("file:/C:",0)){
str=str.substring(6);
}
else{
str=str.substring(5);
}
url = "jdbc:derby:" + str + "database/game_db";
System.out.println("Database url "+url);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static ConnectionHelper getInstance()
{
if (instance == null)
instance = new ConnectionHelper();
return instance;
}
public static Connection getConnection() throws java.sql.SQLException
{
return DriverManager.getConnection(getInstance().getUrl());
}
public static void closeConnection(Connection c)
{
try
{
if (c != null)
{
c.close();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
There is NO problem with multiple connections in embedded mode. Full stop.
That said, what you may have come across, is that only one jvm process can access the Derby database files at a time. But that jvm may well have 1000s of threads each with their own connection to Derby (resources permitting, of course).