Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I have two kind of methods to remove JTable selected row.
I create this methods in my GUI Class:
First:
public void dellAction() {
if (table.getSelectedRow() > -1) {
int rowToDelete = table.getSelectedRow();
int rowToModel = table.convertRowIndexToModel(rowToDelete);
Object rowId = table.getValueAt(rowToModel, 0);
try {
Connection con;
PreparedStatement ps = null;
con = DriverManager.getConnection(...);
ps = con.prepareStatement("delete from table where id=?");
ps.setObject(1, rowId);
if (ps.executeUpdate() == 1) {
model1.removeRow(rowToModel);
}
} catch (SQLException sqle) {
sqle.printStackTrace();
}
} else JOptionPane.showMessageDialog(null, "Select A Row");
}
Second:
public void delete(DefaultTableModel model, int modelRow) {
if (table.getSelectedRow() > -1) {
Object rowId = model.getValueAt(modelRow, 0);
try {
Connection con;
PreparedStatement ps = null;
con = DriverManager.getConnection(...);
ps = con.prepareStatement("delete from table where id=?");
ps.setObject(1, rowId);
if (ps.executeUpdate() == 1) {
model.removeRow(modelRow);
}
} catch (SQLException sqle) {
sqle.printStackTrace();
}
} else {
JOptionPane.showMessageDialog(null, "Select A Row");
}
}
The question depends on the context of your application. In a perfect world, your TableModel would be modelling data from some kind of factory/controller that was responsible for managing the data, which would read/write to some kind of data source.
This would allow your TableModel the opportunity to simply not care where the data was coming from or going to, only that it had some means of performing these actions.
The same would go for your JTable, it should have no idea about the source of the data, only that the TableModel provides the required contract it needs to fulfill its responsibility.
This, then, raises the question of, who should actually perform what jobs.
In this scenario, I would provide some means for the factory/controller to alert registered listeners to changes. This would decouple the API in such away that any part of the program would then be able to modify the factory/controller without needing to know about everybody else who might be using that factory/controller, but still be able to react to those changes.
So, my answer would generally be neither...but...your second one comes closest to achieving this, but I'm concerned about the need to extract data from the model in this way, but that's me...
This is, of course, is just my opinion, based on the factory, observer, producer-consumer and model-view-controller patterns
Related
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.
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 6 years ago.
Improve this question
I need to create a sql sequence in sql server programmatically from Java and I should be able to retrieve the continuous value from the sequence to program. First of all can I do so? If so how?
It's possible as all SQL servers provide some functionality and guarantee ACID rules. Even with very simple old MySql engine which didn't support transactions it's achievable. The easiest and widely supported approach is:
CREATE TABLE SequenceValue (
sequenceIdentifier varchar(124) NOT NULL PRIMARY KEY,
sequenceValue INT NOT NULL;
);
All you need to do in the program is:
Connection con = dataSource.getConnection();
try {
con.setAutoCommit(true);
PreparedStatement st = con.prepareStatement("SELECT sequenceValue SequenceValue WHERE sequenceIdentifier = ?");
st.setString(1, sequenceIdentifier);
SQLException retried = null;
for (;;) {
ResultSet rs = st.executeQuery();
if (!rs.next()) {
if (retried != null)
throw retried;
PreparedStatement ins = con.prepareStatement("INSERT INTO SequenceValue (sequenceIdentifier, sequenceValue) VALUES (?, ?)");
ins.setString(1, sequenceIdentifier);
ins.setLong(2, 0);
try {
ins.executeUpdate();
}
catch (SQLException ex) {
// store the exception and rethrow if next query retry fails
retried = ex;
}
}
else {
long value = rs.getLong(1);
PreparedStatement upd = con.prepareStatement("UPDATE SequenceValue SET sequenceValue = sequenceValue+1 WHERE sequenceIdentifier = ? AND sequenceValue = ?");
upd.setString(1, sequenceIdentifier);
upd.setLong(2, value+1);
if (upd.executeUpdate() == 1)
return value+1;
}
}
}
finally {
con.close();
}
Briefly: The code avoid transactions completely. At the beginning it tries to retrieve the sequence value according to identifier. In case it's not found, it attempts to create it and retries retrieving again. It doesn't fail in case the value was created in the meantime.
If the value is found, it tries to increment it using atomic update on the row. If it succeeds then it returns the incremented value, if not it retries again.
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 7 years ago.
Improve this question
I'm writing a Java Swing program for a college library. This program is connected to an MS Access database.
The program has a JTextField where the "Number" has to be entered. Below the TextField, there's a JButton. After the number is entered and the button is clicked, I want the program to print out the respective "Department"
For example :
When the user types the Number "3" in the JTextField and clicks the 'Enter'
button, I want my program to print out "Computers" i.e the data from the adjoining cell.
How do I achieve this? Thanks in advance!
Start by taking a look at JDBC Database Access.
You will need a JDBC driver for MS Access, UCanAccess is reasonable popular.
You will then need to:
Load the JDBC driver
Connect to the database
Execute a SQL query which can select the data you want based on your critera
Retrieve the data from the resulting data set
For example...
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
try (Connection conn = DriverManager.getConnection("jdbc:ucanaccess://<mdb or accdb file path>", user, password)) {
try (PreparedStatement stmt = conn.prepareStatement("SELECT department FROM Table1 WHERE ID = ?")) {
stmt.setInt(1, 3); // Use a variable for the ID
try (ResultSet rs = stmt.executeQuery()) {
// We're only expecting a single row...
if (rs.next()) {
String department = rs.getString(1);
}
}
}
} catch (SQLException exp) {
exp.printStackTrace();
}
} catch (ClassNotFoundException exp) {
exp.printStackTrace();
}
You might also want to take a look at a SQL Tutorial
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I want to call a method from servlet. I have below class:
public class course {
public ResultSet course_in_dept(String dept_name) {
ResultSet rs = null;
try {
String Query = "select course_id , title from course where dept_name=?";
PreparedStatement pst = Database.dbConnect().prepareStatement(Query);
pst.setString(1, dept_name);
rs = pst.executeQuery();
return rs;
} catch (Exception e) {
Database.error = 1;
return null;
}
}
}
And now I want to call course_in_dept method from this class in doPost method of my servlet. Now how I can handle it?
Try create instance and call it like:
course courseResult = new course();
ResultSet resultSet = courseResult.course_in_dept("Engineering");
There are thee tables inside my database. One is employee, the second is employee_Project, and the third is employee_Reporting. Each table has a common employee_Number as its primary key, and there is a one to many relationship among them such that an employee has many projects and reporting dates.
I have run select * from employee, select * from employee_project, select * from employee_reporting in three data holder classes which have methods fillResultSet(Result set) and List<T> getData(). This is based on a SqlDbEngine class with a runQuery(PreparedStatement,DataHolder) method, and the implementation has been completed.
Now I have to design a getAllEmployee() method along with project and reporting detail with optimal code in java using JDBC. I have used an iterator but this solution is not acceptable; now I have to use a foreach loop.
This is what I have done:
public List<Employee> getAllEmployees() {
EmployeeDataHolderImpl empdataholder = new EmployeeDataHolderImpl();
List<Employee> list_Employee_Add = null;
try {
Connection connection = mySqlDbConnection.getConnection();
PreparedStatement preparedStatement = connection
.prepareStatement(GET_ALL_EMPLOYEE_DETAILS);
mySqlDBEngineImpl.runQuery(preparedStatement, empdataholder);
} catch (SQLException e) {
e.printStackTrace();
}
for (Employee employee : empdataholder.getData()) {
new EmployeeDAOImpl().getProject(employee);
new EmployeeDAOImpl.getReport(employee);
}
list_Employee_Add = empdataholder.getData();
return list_Employee_Add;
}
and make another method
public void getProject(Employee emp) {
EmployeeProjectDataHolderImpl employeeProjectHolder = new EmployeeProjectDataHolderImpl();
try {
Connection connection = mySqlDbConnection.getConnection();
PreparedStatement preparedStatement = connection
.prepareStatement(GET_ALL_PROJECT_DETAILS);
mySqlDBEngineImpl
.runQuery(preparedStatement, employeeProjectHolder);
} catch (SQLException e) {
e.printStackTrace();
}
for (EmployeeProject employee_Project : employeeProjectHolder.getData()) {
if (employee_Project.getEmployeeNumber() == emp.getEmpNumber()) {
emp.getProjects().add(employee_Project);
}
}
}
public void getReport(Employee emp) {
EmployeeReportDataHolderImpl employeeReportHolder = new EmployeeReportDataHolderImpl();
try {
Connection connection = mySqlDbConnection.getConnection();
PreparedStatement preparedStatement = connection
.prepareStatement(GET_ALL_REPORT_DETAILS);
mySqlDBEngineImpl
.runQuery(preparedStatement, employeeReportHolder);
} catch (SQLException e) {
e.printStackTrace();
}
for (EmployeeReport employee_Report : employeeReportHolder.getData()) {
if (employee_Report.getEmployeeNumber() == emp.getEmpNumber()) {
emp.getProjects().add(employee_Project);
}
}
}
}
and same for Employee Reporting but doing, this performance is going to decrease.no body worry about closing connection i will do it
Please tell me how I could improve my solution..
There are some issue with your code.
1.you are initializing EmployeeDAOImpl everytime, rather you can just keep one instance and call the operations over it.
new EmployeeDAOImpl().getProject(employee); new
EmployeeDAOImpl.getReport(employee);
2.I don't see where you close your connection after performing an SQL operation.
You should be having
try {
--code statements
}
catch(SQLException e){
e.printStackTrace();
}
finally{
-- close your connection and preparedStatement
}
Closing database connections is very vital.
If you use your actual code, you will have 3 impacts in your code:
You're opening a connection to get the employee's data.
For every employee, you open (and close) a new connection to get his projects.
For every employee, you open (and close) a new connection to get his reports.
Note that opening a new connection is a performance hit on your application. It doesn't matter if you use an enhanced for-loop or an Iterator, there would be many hits that can slow down your application.
Two ways to solve this problem:
Open a single connection where you run all your select statements. This will be better than opening/closing lot of connections.
Create a single SQL statement to retrieve the employees and the data you need for every employee. It will have better performance for different reasons:
A single connection to the database.
A single query instead of lot of queries to the database (a single I/O operation).
If your rdbms allows it, the query will be optimized for future requests (a single query instead of multiple queries).
I would prefer to go with the second option. For this, I tend to use a method that executes any SQL select statement and return a ResultSet. I'll post a basic example (note, the provided code can be improved depending on your needs), this method could be in your SqlDbEngine class:
public ResultSet executeSQL(Connection con, String sql, List<Object> arguments) {
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = con.prepareStatement(sql);
if (arguments != null) {
int i = 1;
for(Object o : arguments) {
pstmt.setObject(i++, o);
}
}
//method to execute insert, update, delete statements...
rs = pstmt.execute();
} catch(SQLException e) {
//handle the error...
}
return rs;
}
And this other method to handle all the query operation
public List<Employee> getAllEmployee() {
Connection con = null;
ResultSet rs = null;
List<Employee> lstEmployee = new ArrayList<Employee>();
try {
con = mySqlDbConnection.getConnection();
//write the sql to retrieve all the data
//I'm assuming these can be your columns, it's up to you
//this can be written using JOINs...
String sql = "SELECT E.EMPLOYEE_ID, E.EMPLOYEE_NAME, P.PROJECT_NAME, R.REPORT_NAME FROM EMPLOYEE E, PROJECT P, REPORT R WHERE E.EMPLOYEE_ID = P.EMPLOYEE_ID AND E.EMPLOYEE_ID = R.EMPLOYEE_ID";
//I guess you don't need parameters for this...
rs = SqlDbEngine.executeSQL(con, sql, null);
if (rs != null) {
Employee e;
int employeeId = -1, lastEmployeeId = -1;
while (rs.next()) {
//you need to make sure to create a new employee only when
//reading a new employee id
employeeId = rs.getInt("EMPLOYEE_ID");
if (lastEmployeeId != employeeId) {
e = new Employee();
lastEmployeeId = employeeId;
lstEmployee.add(e);
}
Project p = new Project();
Report r = new Report();
//fill values of p...
//fill values of r...
//you can fill the values taking advantage of the column name in the resultset
//at last, link the project and report to the employee
e.getProjects().add(p);
e.getReports().add(r);
}
}
} catch (Exception e) {
//handle the error...
} finally {
try {
if (rs != null) {
Statement stmt = rs.getStatement();
rs.close();
stmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
//handle the error...
}
}
return lstEmployee;
}
Note that the second way can be harder to code but it will give you the best performance. It's up to you to improve the provided methods, some advices:
Create a class that receives a ResultSet and builds a Project instance using the columns name of the ResultSet (similar for Report and Employee).
Create a method that handles the ResultSet and its Statement close.
As a best practice, never use select * from mytable, it's preferable to write the needed columns.
If I understand correctly, your code first loads all EmployeeReport rows and then filters them according to getEmployeeNumber(). You can let your database do this by modifying your SQL query.
Since you didn't show your SQL queries (I assume they're in GET_ALL_REPORT_DETAILS), I'll just make a guess... Try executing SQL like:
select *
from employee_reporting
where employeeNumber = ?
If you put this in a PreparedStatement, and then set the parameter value, your database will only return the data you need. For example:
PreparedStatement pstmt = con.prepareStatement(GET_ALL_REPORT_DETAILS);
pstmt.setInt(1, employee.getEmployeeNumber());
That should return only the EmployeeReport records having the desired employeeNumber. In case performance is still an issue, you could consider adding an index to your EmployeeReport table, but that's a different story...