
CRUD application is a common basic system that utilizes data for entries, modification, removal or backup. CRUD stands for Create, Read, Update, and Delete. These names serve as the main features for the authorized user to assess the system with data access and manipulation. These type of systems are contemporary attribute for modern management systems that handle company databases which include products, customers, employees, and other entity records that are essential for the industrial revolution. A simple CRUD system is applied commonly for academic projects or case study as requirements and software training. In this article, you will be guided in developing a quick simple CRUD application in Java that includes a portable database file that can be linked to the application, drag-and-drop technique to create your user interface, and important code lines that are based for Java development. The example program is related to customer management.
Remember to follow the main steps through order so you can benefit a CRUD development in time and other resources. If you are learning this tutorial for an assessment, exam, or even a case study deadline, time-management is essential to accomplish it so a tip is to open the necessary programs already so you can switch easily to applications for your next work, but I suggest this tip for devices with higher specs so currently opened applications won’t bloat your system resources, like memory and CPU, and affect your system performance. Another thing is to setup already your data source with data also included, if you are already given the format and content to fill.
Before we start, you need these programs and files to create the application:
- SQLiteStudio
- Eclipse IDE for Java Developers
- WindowBuilder for Eclipse (tutorial for installation)
- SQLite Connector for Java
Here are the steps in developing a simple CRUD Java application:
1) Setting up database
For this purpose of a CRUD application with minimal requirements to setup, we will be using SQLite. Click on this link to view the tutorial on how to set up database with SQLiteStudio. Now if you have already setup your database with the file, it’s time to create the Java Application.
2) Creating CRUD Java application
In this tutorial, Eclipse IDE will be used for developing the application. It is assumed that you are knowledgeable in using Eclipse and coding with Java, so the tutorial will direct to setting up the Java Project and employ a hybrid MVC framework style.- Open Eclipse IDE and create a Java Project.
- After creating a Java Project with a name (eg. Sample Project), right-click your project and go to Build Path > Configure Build Path.
- Before configuring build path, make sure you have saved the SQLite JDBC Connector in a directory or directly to your project directory so you can easily access it in your work space. Typical name of file would look like this: sqlite-jdbc-<version number>.
- In Build Path dialog, head to Libraries tab and select Add JARs or Add External JARs to locate the SQLite JDBC file and add it to the build path. Click OK to proceed to setting the application.
- You need to create a user interface or UI that is easy to create and maintain by drag-and-drop instead of coding it. After WindowBuilder is installed to Eclipse, we can finally create first a UI to visualize your data representation and control. It will also help you to realize other data entities that needs to be shown for the user and implement the models later. Create a package named ‘ui’ for UI classes. Then create a main UI class for your CRUD application by right-clicking ‘ui’ package, select New > Other. Navigate to WindowBuilder > Swing Designer > Application Window then Next to name your file. In this case, I named it ‘CustomerUI’.
- You will see the source code currently opened in Source tab at the bottom. Click the Design tab right next to it to load the UI designing area and begin dragging components to layout your UI.
- You can now drag components directly to the window shown as it is an absolute layout. You are free to choose other layouts at the Properties or Palette panel and play with the components from how it will look for different layouts. Following is already set with custom variable names and other settings.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterspackage ui; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.JButton; import java.awt.Font; import java.awt.Color; public class CustomerUI { private JFrame frame; private JTextField custIdTF; private JTextField custNameTF; private JTextField paytermTF; private JTextField addressTF; private JTextField companyTF; private JButton nextBtn; private JButton previousBtn; private JButton addBtn; private JButton updateBtn; private JButton deleteBtn; private JButton firstBtn; private JButton lastBtn; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { CustomerUI window = new CustomerUI(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public CustomerUI() { initialize(); } /** * Initialize the contents of the frame. * Sets all of the components and linked to an action listener that handles the control */ private void initialize() { frame = new JFrame(); frame.setBounds(100, 100, 570, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout(null); JLabel custIdLbl = new JLabel("Customer ID:"); custIdLbl.setBounds(58, 10, 76, 16); frame.getContentPane().add(custIdLbl); custIdTF = new JTextField(); custIdTF.setBounds(141, 7, 376, 22); frame.getContentPane().add(custIdTF); custIdTF.setColumns(10); custIdTF.setEditable(false); JLabel custNameLbl = new JLabel("Customer name:"); custNameLbl.setBounds(38, 39, 96, 16); frame.getContentPane().add(custNameLbl); custNameTF = new JTextField(); custNameTF.setBounds(141, 36, 376, 22); custNameTF.setColumns(10); frame.getContentPane().add(custNameTF); JLabel payTermLbl = new JLabel("Payterm:"); payTermLbl.setBounds(82, 68, 52, 16); frame.getContentPane().add(payTermLbl); paytermTF = new JTextField(); paytermTF.setBounds(141, 65, 376, 22); paytermTF.setColumns(10); frame.getContentPane().add(paytermTF); JLabel addressLbl = new JLabel("Address:"); addressLbl.setBounds(83, 97, 51, 16); frame.getContentPane().add(addressLbl); addressTF = new JTextField(); addressTF.setBounds(141, 94, 376, 22); addressTF.setColumns(10); frame.getContentPane().add(addressTF); JLabel companyLbl = new JLabel("Company:"); companyLbl.setBounds(76, 126, 58, 16); frame.getContentPane().add(companyLbl); companyTF = new JTextField(); companyTF.setBounds(141, 123, 376, 22); companyTF.setColumns(10); frame.getContentPane().add(companyTF); nextBtn = new JButton(">"); nextBtn.setForeground(Color.BLUE); nextBtn.setBounds(289, 191, 125, 25); frame.getContentPane().add(nextBtn); previousBtn = new JButton("<"); previousBtn.setForeground(Color.BLUE); previousBtn.setBounds(152, 191, 125, 25); frame.getContentPane().add(previousBtn); addBtn = new JButton("ADD"); addBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); addBtn.setBounds(15, 228, 173, 25); frame.getContentPane().add(addBtn); updateBtn = new JButton("UPDATE"); updateBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); updateBtn.setBounds(200, 228, 166, 25); frame.getContentPane().add(updateBtn); deleteBtn = new JButton("DELETE"); deleteBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); deleteBtn.setBounds(378, 228, 173, 25); frame.getContentPane().add(deleteBtn); firstBtn = new JButton("<<"); firstBtn.setForeground(Color.BLUE); firstBtn.setBounds(15, 191, 125, 25); frame.getContentPane().add(firstBtn); lastBtn = new JButton(">>"); lastBtn.setForeground(Color.BLUE); lastBtn.setBounds(426, 191, 125, 25); frame.getContentPane().add(lastBtn); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.setTitle("Customer Management"); } }
- We leave the partially completed UI later to proceed in creating the data entities as objects to implore Object Oriented Programming. For the sample tutorial, customer is the entity to be created an object in a package named ‘domain’. The following is the sample code that defines Customer class, together with its variables, constructor, and setter and getter methods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterspackage domain; public class Customer { private String custId, custName, payTerm, company, address; // Constructor public Customer(String custId, String studName, String payTerm, String address, String company) { this.custId = custId; this.custName = studName; this.payTerm = payTerm; this.address = address; this.company = company; } // Setter methods public void setCustId(String custId) { this.custId = custId; } public void setCustName(String custName) { this.custName = custName; } public void setPayTerm(String payTerm) { this.payTerm = payTerm; } public void setCompany(String company) { this.company = company; } public void setAddress(String address) { this.address = address; } // Getter methods public String getCustId() { return custId; } public String getCustName() { return custName; } public String getPayTerm() { return payTerm; } public String getCompany() { return company; } public String getAddress() { return address; } }
- Next we will create a controller to connect and handle the objects with the UI. Create a package named ‘techserv’ and create a class named ‘CustomerDA’ under the package. The code provided is explanatory through comments provided.
Note: Delete function does not totally delete record from database and applies stamp value from database to inactive to mark it as deleted. This is a basic principle of CRUD to preserve historical data as backup and retrievable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterspackage techserv; import java.sql.*; import java.util.ArrayList; import javax.swing.JOptionPane; import domain.Customer; public class CustomerDA { private ArrayList<Customer> customerList; private int recordCursor; private Connection connection; // Database file directory saved directly on the project private final String dbDir = "..\\Sample Project\\SampleDB.db"; // Constructor to initialize set of actions public CustomerDA() { // Set first record to be shown setRecordCursorAtStart(); // Initialize and set database connection from SampleDB.db setConnection(); // Populate application with customer data populateCustomerList(); } public void setRecordCursorAtStart() { recordCursor = 0; } // States the database connection for SQLite that include the recently added SQLite JDBC private void setConnection() { try { // Register SQLite JDBC to class path Class.forName("org.sqlite.JDBC"); // Get SQLite connection from given database connection = DriverManager.getConnection("jdbc:sqlite:" + dbDir); } catch (ClassNotFoundException | SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Retrieve customer record list from database to customerList variable private void populateCustomerList() { customerList = new ArrayList<Customer>(); try { PreparedStatement ps = connection.prepareStatement("SELECT * FROM customer"); ResultSet rs = ps.executeQuery(); Customer cust; while(rs.next()) { // Filter records that are stamped inactive or considered deleted if(rs.getString("stamp").contains("inactive")) continue; cust = new Customer(rs.getString("custId"), rs.getString("name"), rs.getString("payterm"), rs.getString("address"), rs.getString("company")); customerList.add(cust); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // This method is usable to pass query to be committed and update the database private void commitStatement(String query) { try { // Prepare string query as statement to execute PreparedStatement ps = connection.prepareStatement(query); // Execute statement for database to update ps.executeUpdate(); } catch (SQLException e) { // Inform that exception occurred from executing statement JOptionPane.showMessageDialog(null, "An error occured due invalid/conflict in customer data inputted.", "", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } // Update customerList variable populateCustomerList(); } // Adds passed customer object to Customer table public void addCustomer(Customer cust) { commitStatement(String.format("INSERT INTO customer VALUES ('%s', '%s', '%s', '%s', '%s', 'active')", cust.getCustId(), cust.getCustName(), cust.getPayTerm(), cust.getAddress(), cust.getCompany())); setRecordCursorAtEnd(); } // Updates passed old customer info to latest info public void updateCustomer(String oldCustId, Customer cust) { commitStatement(String.format("UPDATE customer SET custId = '%s', name = '%s', payterm = '%s', address = '%s', company = '%s' WHERE custId = '%s'", cust.getCustId(), cust.getCustName(), cust.getPayTerm(), cust.getAddress(), cust.getCompany(), oldCustId)); } // Deletes customer from database by updating stamp state to inactive public void deleteCustomer(String custId) { commitStatement(String.format("UPDATE customer SET stamp = 'inactive' WHERE custId = '%s'", custId)); setRecordCursorAtStart(); } public Customer getCurrentCustomer() { return customerList.get(recordCursor); } public void setRecordCursorAtEnd() { recordCursor = customerList.size()-1; } public Customer getNextCustomer() { return customerList.get( recordCursor = recordCursor >= customerList.size()-1? customerList.size()-1:++recordCursor); } public Customer getPreviousCustomer() { return customerList.get( recordCursor = recordCursor <= 0? 0:--recordCursor); } public Customer getFirstCustomer() { return customerList.get(recordCursor = 0); } public Customer getLastCustomer() { return customerList.get(recordCursor = customerList.size()-1); } public ArrayList<Customer> getCustomerList() { return customerList; } }
- Final code setup is to use the CustomerDA data access controller to be linked with the UI to have it dynamic and interactive with the user. Meaning that we will imply controller codes for CustomerUI directly. The code provided applies for the updated CustomerUI again explanatory through comments embedded per code line section.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characterspackage ui; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; import domain.Customer; import techserv.CustomerDA; import javax.swing.JButton; import java.awt.Font; import java.awt.Color; public class CustomerUI { private JFrame frame; private JTextField custIdTF; private JTextField custNameTF; private JTextField paytermTF; private JTextField addressTF; private JTextField companyTF; private JButton nextBtn; private JButton previousBtn; private JButton addBtn; private JButton updateBtn; private JButton deleteBtn; private CustListener custListener; private JButton firstBtn; private JButton lastBtn; private CustomerDA custDA; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { CustomerUI window = new CustomerUI(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public CustomerUI() { custDA = new CustomerDA(); custListener = new CustListener(); initialize(); updateCustomerForm(); // Set text fields to read mode areTextFieldsEditable(false); } /** * Initialize the contents of the frame. * Sets all of the components and linked to an action listener that handles the control */ private void initialize() { frame = new JFrame(); frame.setBounds(100, 100, 570, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout(null); JLabel custIdLbl = new JLabel("Customer ID:"); custIdLbl.setBounds(58, 10, 76, 16); frame.getContentPane().add(custIdLbl); custIdTF = new JTextField(); custIdTF.setBounds(141, 7, 376, 22); frame.getContentPane().add(custIdTF); custIdTF.setColumns(10); custIdTF.setEditable(false); JLabel custNameLbl = new JLabel("Customer name:"); custNameLbl.setBounds(38, 39, 96, 16); frame.getContentPane().add(custNameLbl); custNameTF = new JTextField(); custNameTF.setBounds(141, 36, 376, 22); custNameTF.setColumns(10); frame.getContentPane().add(custNameTF); JLabel payTermLbl = new JLabel("Payterm:"); payTermLbl.setBounds(82, 68, 52, 16); frame.getContentPane().add(payTermLbl); paytermTF = new JTextField(); paytermTF.setBounds(141, 65, 376, 22); paytermTF.setColumns(10); frame.getContentPane().add(paytermTF); JLabel addressLbl = new JLabel("Address:"); addressLbl.setBounds(83, 97, 51, 16); frame.getContentPane().add(addressLbl); addressTF = new JTextField(); addressTF.setBounds(141, 94, 376, 22); addressTF.setColumns(10); frame.getContentPane().add(addressTF); JLabel companyLbl = new JLabel("Company:"); companyLbl.setBounds(76, 126, 58, 16); frame.getContentPane().add(companyLbl); companyTF = new JTextField(); companyTF.setBounds(141, 123, 376, 22); companyTF.setColumns(10); frame.getContentPane().add(companyTF); nextBtn = new JButton(">"); nextBtn.setForeground(Color.BLUE); nextBtn.setBounds(289, 191, 125, 25); nextBtn.addActionListener(custListener); frame.getContentPane().add(nextBtn); previousBtn = new JButton("<"); previousBtn.setForeground(Color.BLUE); previousBtn.setBounds(152, 191, 125, 25); previousBtn.addActionListener(custListener); frame.getContentPane().add(previousBtn); addBtn = new JButton("ADD"); addBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); addBtn.setBounds(15, 228, 173, 25); addBtn.addActionListener(custListener); frame.getContentPane().add(addBtn); updateBtn = new JButton("UPDATE"); updateBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); updateBtn.setBounds(200, 228, 166, 25); updateBtn.addActionListener(custListener); frame.getContentPane().add(updateBtn); deleteBtn = new JButton("DELETE"); deleteBtn.setFont(new Font("Tahoma", Font.BOLD, 13)); deleteBtn.setBounds(378, 228, 173, 25); deleteBtn.addActionListener(custListener); frame.getContentPane().add(deleteBtn); firstBtn = new JButton("<<"); firstBtn.addActionListener(custListener); firstBtn.setForeground(Color.BLUE); firstBtn.setBounds(15, 191, 125, 25); frame.getContentPane().add(firstBtn); lastBtn = new JButton(">>"); lastBtn.addActionListener(custListener); lastBtn.setForeground(Color.BLUE); lastBtn.setBounds(426, 191, 125, 25); frame.getContentPane().add(lastBtn); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.setTitle("Customer Management"); } // Updates form fields with current customer navigated private void updateCustomerForm() { Customer cust = custDA.getCurrentCustomer(); custIdTF.setText(cust.getCustId()); custNameTF.setText(cust.getCustName()); paytermTF.setText(cust.getPayTerm()); addressTF.setText(cust.getAddress()); companyTF.setText(cust.getCompany()); } // Sets form fields to read or edit mode private void areTextFieldsEditable(boolean flag) { custIdTF.setEditable(flag); custNameTF.setEditable(flag); paytermTF.setEditable(flag); addressTF.setEditable(flag); companyTF.setEditable(flag); } // An action listener class that uses the methods from CustomerDA to give actions // in the components when users interact with it class CustListener implements ActionListener { @Override public void actionPerformed(ActionEvent ev) { String ac = ev.getActionCommand(); switch(ac) { case ">": nextCust(); break; case "<": prevCust(); break; case ">>": lastCust(); break; case "<<": firstCust(); break; case "ADD": setEditMode("ADD"); break; case "UPDATE": setEditMode("UPDATE"); break; case "SAVE ADD": addCust(); resetEditMode(); break; case "SAVE UPDATE": updateCust(); resetEditMode(); break; case "CANCEL": resetEditMode(); break; case "DELETE": deleteCust(); break; } } // Resets form to read mode private void resetEditMode() { nextBtn.setText(">"); previousBtn.setText("<"); areTextFieldsEditable(false); addBtn.setEnabled(true); updateBtn.setEnabled(true); deleteBtn.setEnabled(true); firstBtn.setEnabled(true); lastBtn.setEnabled(true); updateCustomerForm(); } // Utilizes form to add or update mode private void setEditMode(String mode) { areTextFieldsEditable(true); if(mode.equals("ADD")) clearForm(); else if(mode.equals("UPDATE")) custIdTF.setEditable(false); nextBtn.setText("CANCEL"); previousBtn.setText("SAVE " + mode); firstBtn.setEnabled(false); lastBtn.setEnabled(false); addBtn.setEnabled(false); addBtn.setEnabled(false); updateBtn.setEnabled(false); deleteBtn.setEnabled(false); } private void clearForm() { custIdTF.setText(""); custNameTF.setText(""); paytermTF.setText(""); addressTF.setText(""); companyTF.setText(""); } // Confirmation to delete selected customer private void deleteCust() { int res = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete customer?", "", JOptionPane.YES_NO_OPTION); if(res == 0) { custDA.deleteCustomer(custIdTF.getText()); updateCustomerForm(); } } // Update customer record to database from form fields private void updateCust() { custDA.updateCustomer(custIdTF.getText(), new Customer( custIdTF.getText(), custNameTF.getText(), paytermTF.getText(), addressTF.getText(), companyTF.getText()) ); updateCustomerForm(); } // Add customer record to database from form fields private void addCust() { custDA.addCustomer( new Customer( custIdTF.getText(), custNameTF.getText(), paytermTF.getText(), addressTF.getText(), companyTF.getText()) ); updateCustomerForm(); } // Navigate to previous customer record private void prevCust() { custDA.getPreviousCustomer(); updateCustomerForm(); } // Navigate to next customer record private void nextCust() { custDA.getNextCustomer(); updateCustomerForm(); } // Navigate to first customer record private void firstCust() { custDA.getFirstCustomer(); updateCustomerForm(); } // Navigate to last customer record private void lastCust() { custDA.getLastCustomer(); updateCustomerForm(); } } }
Complete view of the packages performed and its contents are shown:

Here is the completed CRUD UI application:

To recap, you have learned a hierarchical process of developing a CRUD Java UI application. You can now implement this by setting up your database for 5 minutes where data was already provided. Java UI setup and configuration for around 3 minutes where WindowBuilder was already installed and usable. Java coding for about 20 minutes with short testing and finalization for 2 minutes which adds up to 30 minutes in total. Hope this tutorial has provided you with basic quick setup of a simple CRUD application and get advance with the knowledge you’ve gained!
You can download the codes in the Github repository.
What other possible techniques should have been applied to make this development faster than the said time?
What other possible techniques should have been applied to make this development faster than the said time?
Create a basic Java Swing application HostBet with a form for adding, viewing, updating, and deleting records,
ReplyDelete