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.
Related
I'm getting the SQLNonTransientException error when trying to update one of my rows in a H2 database.
public static void setNewServiceInformationsToShown() {
try (Connection conn = DriverManager.getConnection("jdbc:h2:" + Main.config_db_location,
Main.config_db_username, Main.config_db_password)) {
//read data from database
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM BCSTASKS_SERVICE");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
if(rs.getString("Status").equals("Neu") && rs.getBoolean("wasShown") == false) {
rs.updateBoolean("WASSHOWN", true);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
The error message already suggests that I should use conn.createStatement and set the ResultSet to CONCUR_UPDATABLE. The error occurs at the line with rs.updateBoolean(...);
Error Message:
The result set is readonly. You may need to use conn.createStatement(.., ResultSet.CONCUR_UPDATABLE). [90140-210]
The problem is I don't know where and how I should use this method. In the same function or at the start of the program?
Most DB code I see doesn't attempt to use the fact that resultsets are updatable, and will instead fire off an additional UPDATE query, which works fine.
However, sure, H2 supports updateable resultsets too. However, some of the features that ResultSets have actually have quite a cost; the DB engine needs to do a boatload of additional bookkeeping to enable such features which have a performance cost. Lots of database queries are extremely performance sensitive, so by default you do not get the bookkeeping and therefore these features do not work. You need to enable them explicitly, that's what the error is telling you.
You're currently calling the 'wrong' preparedStatement method. You want the more extended one, where you pick and choose which additional bookkeeping you want H2 to do for you, in order to enable these things. You want this one.
conn.prepareStatement(
"SELECT * FROM BCSTASKS_SERVICE",
ResultSet.TYPE_SCROLL_INSENSITIVE, // [edited]
ResultSet.CONCUR_UPDATABLE);
That CONCUR_UPDATABLE thing is just a flag you pass to say: Please do the bookkeeping so that I can call .update.
[edited] This used to read 0 before, but as #MarkRotteveel pointed out, that's not valid according to the documentation.
You have to put update query for update data in database but you are going with select query that is the problem.
Select query is used if you have to fetch data from database.
Update query is used for update data in database where data already stored in database but you just overwrite data.
Here down is modified code:
public static void setNewServiceInformationsToShown() {
try (Connection conn = DriverManager.getConnection("jdbc:h2:" + Main.config_db_location,
Main.config_db_username, Main.config_db_password)) {
PreparedStatement stmt = conn.prepareStatement("UPDATE BCSTASKS_SERVICE SET wasShown = ? WHERE status = ? AND wasShown = ?");
stmt.setBoolean(1, true);
stmt.setString(2, "Neu");
stmt.setBoolean(3, false);
stmt.executeUpdate();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
You need to create a separate query/prepareStatement for an update. In your case as far as I can see you need only one update query:
conn.prepareStatement("UPDATE BCSTASKS_SERVICE SET WASSHOWN=true where
Status = 'Neu' and wasShown = false "
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 ^^
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 am trying to build a library management desktop app by netbeans.
I succeeded in connecting database and adding new book and member information in database table.
Now I have tried to search information by id in table that is unique and want to show related information somewhere, such as in a Label or in a Text Field but I don't know the coding for that.
I have learned simple core java and before it a use discretionary and list to Store my infomation but in database connection how can I use if else clause ex.:
if(list-name.contains (book id))
{
system.out.println("the book id already registered.");
}
else
{
system.out.println("tthis book id is available.");
}
How can I write such as expression for database tables?
you should try to read jdbc connection, and then take this demo example to raed out it helpful for you
try{
Connection con1;
Class.forName("com.mysql.jdbc.Driver");
con1=(Connection)DriverManager.getConnection("jdbc:mysql://192.168.101.1:3306/dbname","username","password");
PreparedStatement ps1=(PreparedStatement)con1.prepareStatement("SELECT * from tablename where columnname=valueofid");
String str;
ResultSet rs1=ps1.executeQuery();
while(rs1.next()){
int id=rs1.getInt("ID");
String bookname=rs1.getString("clnmae1");
String bookauthor=rs1.getString("clname2");
//// there you can use label settext() method where to show your data
}
con1.close();
} catch(Exception ex){
out.print(ex);
}
I have been able to link postgresql with java. I want the user to input a name in a text box in java and a search is performed and checks if the name exists in the database.
My code so far:
String hostname=this.hostNameText.getText();
try
{
s = connection.createStatement();
String q="SELECT * FROM hostdetails WHERE \"HOSTNAME\" = "+hostname;
rs = s.executeQuery(q);
}catch(Exception e)
{
System.out.println("Problem in searching the database 1");
}
I am getting problem to link to the table hostdetails. Please note that hostdetails contain a field nammed HOSTNAME(in capital letters). When I run the above code, I get "Problem in searching the database 1"is displayed. Kindly please help me:)
Try using parameterized queries to protect against SQL injection. Use as follows:
String hostname=this.hostNameText.getText();
try
{
String q="SELECT * FROM hostdetails WHERE \"HOSTNAME\" = ?"; //notice change here
//and use params like this
PreparedStatement pStmnt = connection.prepareStatement(q);
pStmnt.setString(1, hostname);
rs = pStmnt.executeQuery(q);
}catch(Exception e)
{
//error handling here
}