I am implementing the search book frame in my library management system project. In this frame, I want to check the availability of the book. I have two database tables:
1 Book:-which keeps the records of all the books in the library
2 Issuebook;-which keeps the record of issued book
When I am running the frame, the JTable gets populated with the same value thrice. The output is attached after the code. I am unable to find the problem. Here's my code:
public void actionPerformed(ActionEvent e) {
String bookname=tfBookName.getText();
int count=0;
try{
con=DemoConnection.getConnection();
ps=con.prepareStatement("select book.bookid from book,issuebook where book.bookid!=issuebook.bookid and bookname=?");
ps.setString(1, bookname);
rs=ps.executeQuery();
while(rs.next())
{
count++;
String bookid =rs.getString(1);
String availability="Available";
Object[] row = { bookid, bookname, availability};
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.insertRow(0,row);
}
ps1=con.prepareStatement("select book.bookid from book,issuebook where book.bookid=issuebook.bookid and bookname=?");
ps1.setString(1, bookname);
rs1=ps1.executeQuery();
while(rs1.next())
{
String bookid =rs1.getString(1);
String availability="Issued";
Object[] row = { bookid, bookname, availability};
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.insertRow(0,row);
}
if(rs==null&&rs1==null)
{
JOptionPane.showMessageDialog(frame, "Book named"+bookname+"does not exist!!");
}
else if(rs==null&&rs!=null)
{
JOptionPane.showMessageDialog(frame, "All the copies of"+bookname+" book are issued!!");
}
else if(rs!=null&&rs==null)
{
JOptionPane.showMessageDialog(frame, "All the copies of"+bookname+" book are avaialble!!");
}
else if(rs!=null&&rs!=null)
{
JOptionPane.showMessageDialog(frame, count+" copies of"+bookname+" book is avaliable!!");
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
});
Here's output. When the book which is issued, it is shown in the table; no duplicate entries were filled up, but duplicate entries get filled in table for the available books.
As #Blip stood out, the problem lies in your SQL query, especially the first one
select book.bookid from book,issuebook where book.bookid!=issuebook.bookid and bookname=?
In this query, you get the book.bookid each time it is different from an issuebook.bookid. So as you have 3 records in your issuebook table, you get 3 results when a book is not present in this table. Directly trying this query on your console should point this out.
The solution can be to modify your query as
select book.bookid, IF(issuebook.bookid IS NULL, 'Available', 'Issued') as availability from book,issuebook where LEFT JOIN availability ON (book.bookid, issuebook.bookid) and bookname=?
I'm not very used to MySQL and the "LEFT JOIN" notation, but the idea is to automatically get the availability status depending on weither or not the bookid is present in the issuebook table or not. So maybe there is some syntax flaws in my sample query...
Anyway like this you just have to do ONE SQL query (get rid of this ps1, res1...) and get the availability with
String availability=rs.getString(2);
If you are not familiar with SQL JOIN, I advise to document yourself on the subject :).
Hope this will help ;)
Related
I've encountered a bit of a perplexing problem. I've got this simple method for extracting data from a table using SELECT *... However, when it iterates through the table it stops the iteration before it's gone through all entries in said table. I've used the debugger to the extent of eliminating the problem areas to when the rows are added to the ArrayList. But still, it stops before it should stop. Any ideas?
public static ArrayList<Actors> acList() throws Exception {
ArrayList<Actors> acList = new ArrayList<Actors>();
try {
getConnection();
PreparedStatement st = conn.prepareStatement("SELECT * FROM Actors");
ResultSet rst = st.executeQuery();
Actors ac;
while (rst.next()) {
ac = new Actors(rst.getInt("ActorId"), rst.getString("fName"), rst.getString("eName"),
rst.getInt("Age"), rst.getInt("NoOfCredits"), rst.getString("Country"));
acList.add(ac);
}
} catch (Exception e) {
}
return acList;
}
Found the answer, posting if anyone else encounters similar problems. What had happened was that one row in my mysql table had an entry (Which i believed to have deleted) that wasn't matching types with what I was trying to extract. The list attempted to claim an int but the value in the row was varchar. Edited the table so it was correct types. Now it works ^^
Cheers everyone, beginner here!.
I'm currently working on a Java application to keep track of the inventory in our warehouse. It's all on localhost until it's finished. I've created two tables in MySQL database: one table shows the article code, location and quantity (VOORRAADSYSTEEM); the other table shows article code and description (STAMDATA).
In my GUI, I've got a JTable which loads data from VOORRAADSYSTEEM, and on mouseclickevent (getSelectedRow) shows the data in the corresponding JTextFields (so far so good). The only field not showing is the description field (which should be read from the STAMDATA table).
I've tried creating a method for this specific part of the program. The method runs a query to the second table using a inner join to the first table. Here's the code below.
private void LoadDescription() {
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ABEL?zeroDateTimeBehavior=convertToNull", "root", "");
String sql = "SELECT DESCRIPTION FROM VOORRAADSYSTEEM JOIN STAMDATA ON ARTICLECODE = ARTICLENUMBER WHERE ARTICLECODE="+jComboBox1.getSelectedItem();
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
pst.setString(2, sql);
descriptionTxt.setText(rs.getString(sql));
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
At this moment I'm not exactly sure how to approach this problem. I'm also going to try using foreign keys. Any help would be appreciated.
There are better ways to handle what you want to do. For instance you could get all the information you need with one query by joining the table on a common column (ARTICLENUMBER and ARTICLECODE) and then display it.
Right now it looks/sounds like you might be trying to get all the information with two queries.
However, there are some errors with your load description method:
private void LoadDescription() {
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ABEL?zeroDateTimeBehavior=convertToNull", "root", "");
String sql = "SELECT DESCRIPTION FROM VOORRAADSYSTEEM JOIN STAMDATA ON ARTICLECODE = ARTICLENUMBER WHERE ARTICLECODE="+jComboBox1.getSelectedItem();
ResultSet results = conn.createStatment().executeQuery(sql);
if(results.next()) //make sure something was returned to avoid null pointer exception
descriptionTxt.setText(rs.getString("DESCRIPTION"));
else
JOptionPane.showMessageDialog(null, "no results returned");
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
}
This should work a little better for you.
Kindly help me to solve this problem, also tell me how to display data on the table by using condition on comboBox. Following is the code and Output. Please help me, as I have to show this to my instructor tomorrow.
public ArrayList<User> userList() {
ArrayList<User> usersList = new ArrayList<>();
try{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url="jdbc:sqlserver://localhost:1433;databasename=DB_Project;user=User;Password=password";
Connection con= DriverManager.getConnection(url);
String query = "SELECT * FROM tbl_Income";
Statement st=con.createStatement();
ResultSet rs= st.executeQuery(query);
User user;
while(rs.next()){
user= new User(rs.getInt("Amout"),rs.getString("Date"),rs.getString("Source"));
usersList.add(user);
}
}
catch(Exception e){
JOptionPane.showMessageDialog(null,e);
}
return usersList;
}
public void show_user() {
ArrayList<User> list = userList();
DefaultTableModel model = (DefaultTableModel)Income_Table.getModel();
Object[] row =new Object[3];
for(int i=0;i<list.size();i++){
row[0]=list.get(i).getAmout();
row[1]=list.get(i).getDate();
row[2]=list.get(i).getSource();
model.addRow(row);
}
}
//**********tbl_Expense
public ArrayList<User_E> userList_E() {
ArrayList<User_E> UsersList_E = new ArrayList<>();
try{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String eurl="jdbc:sqlserver://localhost:1433;databasename=DB_Project;user=User;Password=password";
Connection con= DriverManager.getConnection(eurl);
String query_E = "SELECT * FROM tbl_Expense";
Statement stt=con.createStatement();
ResultSet rst= stt.executeQuery(query_E);
User_E user_e;
while(rst.next()){
user_e = new User_E(rst.getString("ExpenseDetail"),rst.getString("Category"),rst.getString("Date"),rst.getInt("Amount"));
UsersList_E.add(user_e);
}
}
catch(Exception e){
JOptionPane.showMessageDialog(null,e);
}
return UsersList_E;
}
public void showuser_E(){
ArrayList<User_E> list_E = userList_E();
DefaultTableModel model_e = (DefaultTableModel)Expense_Table.getModel();
Object[] row_e =new Object[4];
for(int i=0;i<list_E.size();i++){
row_e[0]=list_E.get(i).getAmount();
row_e[1]=list_E.get(i).getDate();
row_e[2]=list_E.get(i).getCategory();
row_e[3]=list_E.get(i).getExpenseDetail();
model_e.addRow(row_e);
}
}
This is the Output, getting 0 instead of original data
I cannot tell what the issue by looking at the code posted. But, the application's database access, querying and showing the data in the GUI need to be structured something like this:
1. Access database and get connection:
Get connection object for the database DB_Project (there is no need to create connection objects twice).
2. Query 1:
Create statement
Query the tbl_Income table and populate the "userList"
Close the statement (this also closes the corresponding result set)
3. Query 2:
Create statement
Query the tbl_Expense table and populate the "userList_E"
Close the statement
4. Close connection (this is optional and depends on application requirement).
5. Display GUI using the queried data:
Show user income JTable using the "userList"
Show user expense JTable using the "userList_E"
NOTES:
Place some debug or log statements in the Java code and verify if there is any data in the tables being queried and also what kind of data it is. Querying the database tables directly and interactively or from the command prompt also helps. Also, after populating the list collections print the lists onto the console using System.out.prinltln() statements to verify if the data is populated to them properly.
How to display based on combo box selection:
Here is the link to Java tutorials on using Swing JComboBox - see the section "Handling Events on a Combo Box".
There are different ways one can build the code to acheive this functionality.
By directly querying the database table using the data selected from
the combo box, or
By filtering the data from the "list" data already queried and populated to it. This option requires the queried data from the database tables be stored in instance variables.
Again, it depends upon the application requirement. In case the database table data is not changing then option 2 is the correct method, otherwise query the database table directly.
One hideous thing: nothing is closed (connection, statement, result set).
Try-with-resources may help here, to automatically close those, even on return, break, raised exception.
public ArrayList<User_E> userList_E() {
ArrayList<User_E> usersList_E = new ArrayList<>();
String eurl = "jdbc:sqlserver://localhost:1433;databasename=DB_Project;"
+ "user=User;Password=password";
String query_E = "SELECT * FROM tbl_Expense";
try (Connection con = DriverManager.getConnection(eurl);
Statement stt = con.createStatement();
ResultSet rst= stt.executeQuery(query_E)) {
while(rst.next()){
User user_e = new User_E(rst.getString("ExpenseDetail"),
rst.getString("Category"),
rst.getString("Date"),
rst.getInt("Amount"));
usersList_E.add(user_e);
}
}
catch(SQLException e){
JOptionPane.showMessageDialog(null, e.getMessage());
}
return usersList_E;
}
Class.forName on the driver class is since years no longer required.
For the error: I can only assume that the application is running out of free connections.
I coded auto suggesting comboBox that retrieve data from SQL database.It was successful.
Then as next step, I want these functionalities to be done,
*When user select a "ItemID" from the comboBox(When the user type first letter of ItemID, suggest list comes and user can select aItemID - successfully coded), JTable's "ItemID" column and other columns that related to that specific "ItemID" must be updated from the database.
I coded updateTable()method as below;
private void updateTable(){
String existID = (String) IDcombo.getSelectedItem();
String sql = "select * from druginfo WHERE ItemId LIKE '"+existID+"%'";
try {
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
saleTable.setModel(DbUtils.resultSetToTableModel(rs));
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, ex);
} }
Well your tablemodel needs to fire according to the event. If only table data changes then it should fire fireTableDataChanged(). If data and structure both changes then it should fire fireTableStructureChanged(). You can refer to the document
If you're still having trouble with this the one way is to call repaint on your table but that's not a very good way of doing things.
I scoured the web and found nothing for this. I have a group of records in a JTable and I need to export these records to an existing table in an MS Access database. I need to be able to append records to this table as there may already be data present.
I've spent the last two days reading up and learning about Jackcess and UcanAccess libraries. I'm absolutely tapped out at this point so if someone would be kind enough to post some code I would really appreciate it.
Edit: 5:15 PM PT
Monolithic task for sure. Thanks to all for the helpful advice. I just now managed to arrive at a solution. I read a post that helped me understand the contents of a jTable are really only there for display purposes and not the ideal source to be using to export data sets to other databases. So I used the ImportUtil in the Jackcess library to directly export the ResultSet to my Access database. The answer was right in front of me the whole time: http://jackcess.sourceforge.net/ (it's the fourth code sample from the top)
So here is the AccessExporter.java class I created for this. It takes three parameters a ResultSet object, "TableName" and a File object defining where the database file is located.
Here's the code:
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.util.ImportUtil;
import java.io.File;
import java.sql.ResultSet;
/**
*
* #author petehahn
*/
public class AccessExporter {
void fillData(ResultSet jTableResults, String dbTableName, File dbFile){
try {
Database dbTarget = DatabaseBuilder.open(dbFile);
new ImportUtil.Builder(dbTarget, dbTableName).importResultSet(jTableResults);
dbTarget.close();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
The SimpleTableDemo from The Java™ Tutorials, which creates and displays a JTable like this
contains a method named printDebugData that writes the table data to the console. We can tweak that code to write the table data to an Access database instead.
We'll assume that you've downloaded UCanAccess and added the required references to your project as illustrated in
Manipulating an Access database from Java without ODBC
We'll also assume that you already have a table named [SimpleTableDemo] in your Access database with fields
ID - AutoNumber, Primary Key
FirstName - Text(255)
LastName - Text(255)
Sport - Text(255)
NumYears - Number(Long Integer)
Vegetarian - Yes/No
The first line in public class SimpleTableDemo sets the DEBUG variable. We need that set to true:
private boolean DEBUG = true;
Then we can modify the printDebugData method to update the database
private void printDebugData(JTable table) {
// modified to write table data to database instead of printing to console
int numRows = table.getRowCount();
javax.swing.table.TableModel model = table.getModel();
try (Connection conn = DriverManager.getConnection(
"jdbc:ucanaccess://C:/Users/Public/Database1.accdb")) {
try (PreparedStatement ps = conn.prepareStatement(
"INSERT INTO SimpleTableDemo (" +
"FirstName, LastName, Sport, NumYears, Vegetarian " +
") VALUES (?,?,?,?,?)")) {
for (int i=0; i < numRows; i++) {
ps.setString(1, (String)model.getValueAt(i, 0)); // FirstName
ps.setString(2, (String)model.getValueAt(i, 1)); // LastName
ps.setString(3, (String)model.getValueAt(i, 2)); // Sport
ps.setInt(4, (int)model.getValueAt(i, 3)); // NumYears
ps.setBoolean(5, (boolean)model.getValueAt(i, 4)); // Vegetarian
ps.executeUpdate();
}
}
System.out.println("Database updated.");
} catch (Exception e) {
e.printStackTrace(System.err);
}
}