Well, I needed to take values from the database, and insert them into the combobox for selection.
Sounds easy enough to do just using 2 classes, UI class and Entity class, which contains all the SQL queries inside (anything to do with database, it's in there):
//This is the UI class
public void fillComboBox(){
Entity et = new Entity();
try{
//call out dbConnector method from Entity class
conn = et.dbConnector();
String query="select distinct Name from DbTable order by Name";
PreparedStatement pst = conn.prepareStatement(query);
ResultSet rs = pst.executeQuery();
while(rs.next()){
//shows topic data in combobox
comboBoxName.addItem(rs.getString("Name"));
}
}
catch(Exception e){
e.printStackTrace();
}
}
//runs method
fillComboBox();
Now, the above output works fine with no hitches. In my form, the combo box displays unique values taken from my database in my specified column.
The problem comes when implementing another tier within it.
In short, I have three classes now.
Class 1: UI -> this class purely handles UI
Class 2: Controller -> this class purely runs methods
Class 3: Entity -> this class purely runs anything that have to do with sql database queries
What I did, was to modify the above code, into this:
This is the UI class:
//Declare Variables
JComboBox comboBoxName = new JComboBox();
Controller ct = new Controller();
comboBoxName.addItem(ct.fillComboBox());
And a certain method within the Controller class:
//Declare Variables
Entity et = new Entity();
public String fillComboBox(){
return et.takeNames();
}
Lastly, my Entity class, which contains all sql queries within.
//Declare all variables first
Connection conn = null;
String task = null, names = null;
String query;
//This method connects to database
//There's nothing wrong with this method, I just placed it here to give a general overview of what this method exactly is for you to understand, as I will be calling it out later. Yes, I removed off the **URL** portion intentionally.
public static Connection dbConnector(){
try{
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:URL");
JOptionPane.showMessageDialog(null, "Connected!");
return conn;
}
catch(Exception ex){
JOptionPane.showMessageDialog(null, ex);
return null;
}
}
public String takeNames(){
try{
conn = dbConnector();
query = "select distinct Name from DbTable order by Name";
PreparedStatement pst = conn.prepareStatement(query);
ResultSet rs = pst.executeQuery();
while(rs.next()){
//shows Name data in combobox
names = rs.getString("Name");
}
pst.close();
}
catch(Exception ex){
ex.printStackTrace();
}
return names;
}
Well, basically, how this "new" implementation runs is that, the UI class calls out the Controller class, which calls out the Entity class, which runs the method inside and parse back values all the way to UI.
This method is useful in the sense that it separates different portions of a program, making it look neater. Too bad it is a headache to implement. >.>
Now, the error in this would be that, it will retrieve only 1 value, instead of multiple values. What it does retrieve is the very first 'distinct' value in that particular column I specified. The remaining 'distinct' values are ignored.
I have a hunch it had everything to do with the rs setting, #:
ResultSet rs = pst.executeQuery();
What I had in mind was that it only takes 1 value and sets it, then ignores the rest. Does anyone have any solutions for this? I tried arraylist but failed on how to store numerous rs values in the arraylist (this really stumped me >.>)
I do apologize for the lengthy post, but I tried my best to do up till what I can, before I got stuck at this part for hours.....
modify takeNames() as follows
public ArrayList<String> takeNames(){
//This will collect all names from db
ArrayList<String> names = new ArrayList<>();
try{
conn = dbConnector();
query = "select distinct Name from DbTable order by Name";
PreparedStatement pst = conn.prepareStatement(query);
ResultSet rs = pst.executeQuery();
while(rs.next()){
//shows Name data in combobox
//Add data to the array list
names.add(rs.getString("Name"));
}
pst.close();
}
catch(Exception ex){
ex.printStackTrace();
}
//Return the array list you created
return names;
}
Modify fillComboBox() as follows
public ArrayList<String> fillComboBox(){
return et.takeNames();
}
And modify the rest as follows
JComboBox comboBoxName = new JComboBox();
Controller ct = new Controller();
ArrayList<String> nameList = ct.fillComboBox();
for(String name : nameList){
comboBoxName.addItem(name);
}
Related
I am writing a Program which tracks the movement of an RFID Tag as it moves between RFID censors. This is mimicking the movement of a wallet between rooms. Each censor will be a door to a different room.
I have a SQLite database which holds the Name of the Card, the Location, and the name of the Tag to differentiate between different cards.
I need an ArrayList which tells me what Tags are currently on the database.
I have a DAO method that displays all the values in a database and stores it in an ArrayList as shown:
SELECT * FROM Wallets;
[name: Henry, location: 0, tag: 5c00ce6df0, name: jim, location: 0, tag: wallet1]
I am trying to write another DAO method that will just display the tags like this:
SELECT Tag FROM Wallets;
[5c00ce6df0, wallet1]
Once i have these values saved in an ArrayList i intend to pass them into another DAO method which takes the tags and returns all the relevant information, like this:
SELECT * FROM Wallets WHERE Tag = 'wallet1';
name: jim, location: 0, tag: wallet1
Here is the code for my getAllWallets() DAO:
public ArrayList<Wallet> getAllWallets() throws SQLException{
Connection dbConnection = null;
Statement statement = null;
ResultSet resultset = null;
String query = "SELECT * FROM Wallets;";
ArrayList<Wallet> list = new ArrayList<>();
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
System.out.println(query);
// execute SQL query
resultset = statement.executeQuery(query);
while (resultset.next()) {
Wallet w = new Wallet(query, 0, query);
w.setName(resultset.getString("Name"));
w.setLocation(resultset.getInt("Location"));
w.setTag(resultset.getString("Tag"));
list.add(w);
}
}
catch (SQLException e) {
System.out.println(e.getMessage());
}
finally
{
resultset.close();
statement.close();
dbConnection.close();
}
return list;
}
Here is what i have tried so far for my getWalletTag() DAO:
public ArrayList<String> getWalletTag() throws SQLException {
Connection dbConnection = null;
ResultSet resultset = null;
Statement statement = null;
ArrayList<String> list = new ArrayList<String>();
String query = "SELECT Tag FROM Wallets;";
try {
dbConnection = getDBConnection();
statement = dbConnection.createStatement();
// execute SQL query
System.out.println(query);
resultset = statement.executeQuery(query);
String tag = tag.toString(); // i know this is totally wrong but i got stuck
list.add(tag);
}
catch (SQLException e) {
System.out.println(e.getMessage());
}
finally
{
if (resultset != null) {
resultset.close();
}
if (statement != null) {
statement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
return list;
}
What i am struggling with is how to get all the values of the Tag column into an array list. Is there an easy way to do this? Any help will be greatly appreciated. Thanks.
In an "ideal universe", you would probably want to use an ORM (like Hibernate), and a framework (like Spring Boot).
Either or both might be "overkill" for your application.
If your goal is to get a "list of tags", then the code you've got looks OK:
Connect to the database.
Make a query.
Copy the resultset into a list of Java objects, one at a time.
Close the DB connection when you're done.
If your goal is to "optimally" find a specific tag (without making another DB query), then perhaps you should use a Java Map or Set instead of an ArrayList.
Should you wish to consider Spring Boot and Sqlite, here are a couple of tutorials:
https://www.baeldung.com/spring-boot-sqlite
http://code-flow-hjbello.blogspot.com/2017/07/using-sqlite-with-jdbc.html
This part of your code seems good:
public ArrayList<Wallet> getAllWallets() throws SQLException{
resultset = statement.executeQuery(query);
while (resultset.next()) {
Wallet w = new Wallet(query, 0, query);
w.setName(resultset.getString("Name"));
w.setLocation(resultset.getInt("Location"));
w.setTag(resultset.getString("Tag"));
list.add(w);
}
...
So one of two choices:
Either forget about getWalletTag(), and just use your wallets to identify tags, or
Use the same query, just save the "tag" column into your array list (instead of anything else).
Option 2:
public ArrayList<String> getWalletTag() throws SQLException {
String query = "SELECT Tag FROM Wallets;";
...
resultset = statement.executeQuery(query);
List<String> tags = new ArrayList<String>();
while (resultset.next()) {
tags.add(resultset.getString("Tag"));
...
... or ...
...
Set<String> tags = new HashSet<String>();
while (resultset.next()) {
tags.add(resultset.getString("Tag"));
This is probably a easy question for you guys but I'm trying to access a variable set by an SQL statement to then be passed into another SQL statement in another class.
The idea is that when the user logs in, I get their StaffID then I want to use that number in another SELECT statement.
I've tried to make the variable public and access it from the other class but it returns empty.
LOGIN CODE:
public static String StaffID;
// SignIn ActionListener
signIn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try{
Class.forName(DRIVER);
// Connection to the Database
con = DriverManager.getConnection(DATABASE_URL,"root","");
// Gets text from textfields and assigns them to variables
s1 = tfUsername.getText();
s2 = tfPassword.getText();
Statement st = con.createStatement();
// SQL Statements
st.executeQuery("SELECT * FROM login WHERE UName= '"+s1+"' and PWord = '"+s2+"'");
// Extracts data from statement to a result set
ResultSet rs = st.getResultSet();
if (rs.next())
{
// Gets text from Textfields and assigns them to variables
StaffID = rs.getString("StaffID");
}
OTHER CLASS:
try{
Class.forName(DRIVER);
// Connection to the Database
con = DriverManager.getConnection(DATABASE_URL,"root","");
signIn sign = new signIn();
//Creates Statement Connection
Statement st = con.createStatement();
// SQL Statements
st.executeQuery("SELECT * FROM rota WHERE StaffID = '"+sign.StaffID+"'");
// Extracts data from statement to a result set
ResultSet rs = st.getResultSet();
if (rs.next()) {
tfRotaTask1.setText(rs.getString("Task1"));
tfRotaTask2.setText(rs.getString("Task2"));
tfRotaTask3.setText(rs.getString("Task3"));
tfRotaTask4.setText(rs.getString("Task4"));
tfRotaTask5.setText(rs.getString("Task5"));
tfRotaTask6.setText(rs.getString("Task6"));
tfRotaTask7.setText(rs.getString("Task7"));
tfRotaTask8.setText(rs.getString("Task8"));
}
else{
//JOptionPane.showMessageDialog(null, "Staff Member Not Found");
}
To put this into context, I'm making a staff managment rota system.
Sorry if my Java seems poor :(
Any help will do.
Ok first thing first, wrap your Queries in One Class for more easy use.
public class QueryUtils
{
public static String staffId(...yourArgs)
{
String staffId = "";
// Make the logic for getting the StringId
return staffId;
}
}
Ok so you can call this query from anywhere in your application. Even from other queries. Use basic OOP and Patter Desings and you will solve this issues.
you don't inti the value of the StaffID until the condition of rs.next() is be true
try to make else statement like this
if (rs.next())
{
// Gets text from Textfields and assigns them to variables
StaffID = rs.getString("StaffID");
}
and then test the value of the StaffID in the other class if it null then you have somthing wrong in the executeQuery
because i don't see any thing wrong in your code
I have two classes, the first is the GUI which has jTable, and the other one for querying database.
Adding rows to the table within the same class works fine. I used this way:
((DefaultTableModel) table.getModel()).addRow(values);
While values is a Object[] holding the row content.
This is working fine. But populating has to be done from another class. So I have in the query class:
((DefaultTableModel) rg.table.getModel()).addRow(values);
While rg is an object of the GUI class. And table is public.
This doesn't do anything not even throwing an exception.
What should I change in my query class? Here's my method in the query class:
public void selectPassengers(int rows) {
PreparedStatement pst = null;
ResultSet rs = null;
String query = "SELECT * FROM brs.passenger";
try {
pst = con.prepareStatement(query);
rs = pst.executeQuery();
Object[] attributes = new Object[9];
Register rg = new Register();
while (rs.next()) {
attributes[0] = String.valueOf(rs.getString(1));
attributes[1] = rs.getString(2);
attributes[2] = rs.getString(3);
attributes[3] = rs.getString(4);
attributes[4] = rs.getString(5);
attributes[5] = rs.getString(6);
attributes[6] = rs.getString(7);
attributes[7] = rs.getString(8);
attributes[8] = rs.getString(9);
((DefaultTableModel) rg.table.getModel()).addRow(attributes);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Fetching data from the DB is fine. I could print them to the console.
jTable is I assume is built correctly. I can tell this because I
can insert rows correctly but only within the GUI class itself (the
class where jTable is there).
Moving the inserting logic to a different class (querying class) is
where I am stuck.
I solved this by calling the frame object before the model object.
So instead of rg.model.addRow();, I used rg.frame.model.addRow();, after making frame public in the GUI class.
I have been always using the following code to add Objects from a ResultSet into a List. However someone commented that it is not very efficient to create a new Object for every dataset in the ResultSet. Is there a better way? Or, is there a whole different way to add Object from a ResultSet to a List?
public static List<Students> selectFromDatabase(Connection conn, Statement stmt){
List<Students> list = new ArrayList<Students>();
String select = "SELECT * FROM students";
ResultSet rs = null;
try{
stmt = conn.createStatement();
rs = stmt.executeQuery(select);
while(rs.next()){
//you have to create a new OBJECT FOR EACH LOOP
Students student = new Students();
student.setStudentId(rs.getInt(1));
student.setName(rs.getString(2));
student.setGpa(rs.getInt(3));
list.add(student);
}
}catch(SQLException e){
System.out.println(e.getMessage());
}
return list;
}
The comments on your OP have pretty much already answered your question, I'll just provide some extra insight.
You have a List that contains Students objects. You populate this List by creating a Students object and adding that object to the List for every result that's in rs. How would you go about doing this if you just made one Students object? You've gotta make as many objects as there are results in rs in order to do what it is you're trying to do. This is pretty much what always happens with these data structures, unless it's an array.
that someone is right at some cost of heavy coding. It is not really needed to create a new object . you can always use the same student object and use set to new values and add to list. Sorry I was about to same object with different references....! Copy pasted and missed to add the code inside the loop ! The edited is was i meant
public static List<Students> selectFromDatabase(Connection conn, Statement stmt){
List<Students> list = new ArrayList<Students>();
String select = "SELECT * FROM students";
ResultSet rs = null;
try{
stmt = conn.createStatement();
rs = stmt.executeQuery(select);
Students student = null;
while(rs.next()){
student = new Students();
//you have to create a new OBJECT FOR EACH LOOP
student.setStudentId(rs.getInt(1));
student.setName(rs.getString(2));
student.setGpa(rs.getInt(3));
list.add(student);
}
}catch(SQLException e){
System.out.println(e.getMessage());
}
return list;
}
Code snippet:
On a button click, actionevent will be called
public void actionPerformed(ActionEvent e)
{
Function f = new Function();
Function is a nested class which i have used to establish the connection with the database.
The code snippet for function class is also provided in the end.
ResultSet rs = null;
String Cid ="cust_id";
String Pno="cust_phone";
String cat="cust_cat";
String start_date="st_date";
String Adv_amt="adv";
String Adv_end="end_date";
String Address="addr";
t2 is the Textfield name which i have used to get entry of customer name. I want to use this customer name as a PK to fetch all the other data about that customer from DB.
rs=f.find(t2.getText());
try{
if(rs.next())
{
t1.setText(rs.getString("cust_id"));
t3.setText(rs.getString("cust_phone"));
t4.setText(rs.getString("cust_cat"));
t5.setText(rs.getString("st_date"));
t6.setText(rs.getString("adv"));
t7.setText(rs.getString("end_date"));
t8.setText(rs.getString("addr"));
}
else
JOptionPane.showMessageDialog(null,"No data for this name");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null,ex.getMessage());
}
}
Here is the code snippet for nested class Function which is inside the main class:
class Function{
Connection con=null;
ResultSet rs= null;
PreparedStatement ps = null;
public ResultSet find(String s)
{
try
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection("jdbc:oracle:thin:#Localhost:1521:xe","system","qwerty");
ps= con.prepareStatement("Select * from gkkdb where cust_name='?'");
ps.setString(1,s);
rs= ps.executeQuery();
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, ex.getMessage());
}
return rs;
}
}
Please help figure out the problem.
Don't put the parameter placeholder ? in single quotes.
This:
ps = con.prepareStatement("Select * from gkkdb where cust_name='?'");
should be
ps = con.prepareStatement("Select * from gkkdb where cust_name = ?");
The ? is not recognized as a placeholder if you enclose it in single quotes.
Sorting out the bind variable will fix your immediate issue.
You should explicitly specify what columns you want selected and that way you'll only get what you need (someone might add a BLOB column later) and you'll get them in the right order (someone might change the table create script before running on another DB instance, although you are looking up the columns by name, a different order would only impact if you were using positional indexes).
Ditto on the other answer re: bind variables (i.e. no quotes)
Plus, "select * from" is never a good idea, ask your DBA.
Obviously your code is for example, but you should make sure you free up any resources (Connection, Statement, ResultSet) as soon as they are done with. Use Java 7 try-with-resources.