I'm building a very simple hotel booking program with JDBC. I have 3 tables
Guests(GuestID,LastName,FirstName,Email,PhoneNumber)
Rooms(RoomNumber,Type,Rate)
Reservation(RoomNumber, CheckInDate, CheckOutDate).
If I choose a date and press "Search" button, the tableview should list all the available rooms. However, mine shows nothing.
Main Window
Empty TableView
The following code is what I did for DataSource class.
public static final String QUERY_VACANCY = "SELECT r.* FROM " + TABLE_ROOMS + " r WHERE NOT EXISTS (SELECT 1 FROM " + TABLE_RESERVATION + " re WHERE " +
"re." + COLUMN_ROOM + "=" + "r." + COLUMN_ROOM + " AND " + "((?>=re." + COLUMN_CHECKIN + " AND ?<re." + COLUMN_CHECKOUT
+ ") OR " + "(?<re." + COLUMN_CHECKOUT + " AND ?>=re." + COLUMN_CHECKIN + ")))";
private PreparedStatement queryVacancy;
private Connection connection;
public boolean open() {
try {
connection = DriverManager.getConnection(CONNECTION_STRING, "mememem", "somethingsomething123");
queryVacancy = connection.prepareStatement(QUERY_VACANCY);
return true;
} catch (SQLException e) {
System.out.println("CANNOT Connect to the DB: " + e.getMessage());
return false;
}
}
public List<Rooms> showSearchResult(Date date) {
try {
queryVacancy.setDate(1, date);
queryVacancy.setDate(2, date);
queryVacancy.setDate(3, date);
queryVacancy.setDate(4, date);
ResultSet resultSet = queryVacancy.executeQuery();
List<Rooms> rooms = new ArrayList<>();
while (resultSet.next()) {
Rooms room = new Rooms();
room.setRoomNumber(resultSet.getInt(COLUMN_ROOM));
room.setType(resultSet.getString(COLUMN_TYPE));
room.setRate(resultSet.getInt(COLUMN_RATE));
rooms.add(room);
}
return rooms;
} catch (SQLException e) {
System.out.println("QUERY FAILED: " + e.getMessage());
return null;
}
}
For the controller, I created the following code.
public class Controller {
#FXML
private TableView<Rooms> roomsTableView;
#FXML
private DatePicker checkindatepicker;
public LocalDate getCheckindatepicker(){
return checkindatepicker.getValue();
}
public void listSearchedRooms(){
Task<ObservableList<Rooms>> task = new GetSearchedRooms();
roomsTableView.itemsProperty().bind(task.valueProperty());
new Thread(task).start();
}
}
class GetSearchedRooms extends Task{
private Controller controller;
#Override
protected ObservableList<Rooms> call() throws Exception {
controller = new Controller();
Date date = Date.valueOf(controller.getCheckindatepicker());
System.out.println(date.toString());
return FXCollections.observableArrayList
(DataSource.getInstance().showSearchResult(date));
}
}
Here is my FXml Code.
<center>
<VBox alignment="CENTER" spacing="40">
<children>
<HBox alignment="CENTER">
<Label text="Date: "></Label>
<DatePicker fx:id="checkindatepicker"></DatePicker>
</HBox>
<Button text="Search" onAction="#listSearchedRooms"></Button>
<Button text="Reserve" onAction="#showReserve"></Button>
<Button fx:id="checkReservation" text="Check Reservation" onAction="#showReservation"></Button>
</children>
</VBox>
</center>
What I understand is that, a String value should replace the "?" parts of PreparedStatement. That's why I did
String date = (java.sql.Date.valueOf(checkindatepicker.getValue())).toString();
in call() method
What should I do?
EDIT: The annotated field should be in Controller class. Due to so, I added private variable checkindatepicker in Controller class. Also, to retrieve its value, I created a method getCheckindatepicker(). Then, I created an instance of Controller class in GetSearchedRooms class. Using getCheckindatepicker() method, I would get the value of the chosen date and convert it to java.sql.Date.
However, it's still not working.
There must be nothing wrong with the PreparedStatement nor showSearchResult() method, because with the following code, the tableview shows the available rooms on August 31st.
class GetSearchedRooms extends Task{
#Override
protected ObservableList<Rooms> call() throws Exception {
String str = "2017-08-31";
Date date = java.sql.Date.valueOf(str);
System.out.println(date.toString());
return FXCollections.observableArrayList
(DataSource.getInstance().showSearchResult(date));
}
}
You can do
class GetSearchedRooms extends Task{
private final Date date ;
GetSearchRooms(Date date) {
this.date = date ;
}
#Override
protected ObservableList<Rooms> call() throws Exception {
return FXCollections.observableArrayList
(DataSource.getInstance().showSearchResult(date));
}
}
And then back in the controller replace
Task<ObservableList<Rooms>> task = new GetSearchedRooms();
with
Task<ObservableList<Rooms>> task =
new GetSearchedRooms(Date.valueOf(checkindatepicker.getValue()));
In both cases the Date class is java.sql.Date.
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 9 years ago.
Improve this question
I have Java Swing application which is designed in poor architecture.
GUI, SQL Statement ... etc, all one class.
Ex. NewEmployee.java have GUI, SQL insert,update,delete & select in this class, there is no separation.
From what I read we should separate the logic from the design.
To be honest I don't know how to do that, or how to understand it.
I need to know how to break down my project so I got : model, view & controller, but I need to know what each one mean & how each one should cooperate with other.
could you help in separating this:
public class PendingOInvoices extends CFrame {
private static final long serialVersionUID = 1L;
private JToolBar toolBar = new JToolBar();
private JPanel panel_1 = new JPanel();
private JLabel label3 = new JLabel();
private CText cSearch = new CText();
private JLabel label2 = new JLabel();
private CDCombo cSearchBy = new CDCombo();
private CBGeneral cMakeBill = new CBGeneral();
private Component component5_1 = Box.createHorizontalStrut(3);
private CBRefreshE cRefresh = new CBRefreshE();
private CBCloseE cClose = new CBCloseE();
private Component component5_3 = Box.createHorizontalStrut(3);
private JLabel label1 = new JLabel();
private CDate cTDate = new CDate();
private MyOutBillingModel model1 = new MyOutBillingModel();
private JPVTableView table1 = new JPVTableView(model1);
private JLabel label = new JLabel();
private CDate cFDate = new CDate();
private CBNewE cNew = new CBNewE();
private CBModifyE cModify = new CBModifyE();
private Component component5 = Box.createHorizontalStrut(3);
private Component component5_2 = Box.createHorizontalStrut(3);
private JLabel label4 = new JLabel();
private CDCombo cFilter = new CDCombo();
public PendingOInvoices () {
setTitle("Out Patients - Pending Encounters");
setFrameIcon("opdbilling");
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
setSize(new Dimension(980, 546));
getContentPane().setLayout(new BorderLayout());
getContentPane().add(panel_1, BorderLayout.NORTH);
panel_1.setMaximumSize(new Dimension(0, 44));
panel_1.setMinimumSize(new Dimension(0, 44));
panel_1.setLayout(null);
panel_1.setPreferredSize(new Dimension(0, 44));
panel_1.add(label3);
label3.setText("Search engine:");
label3.setBounds(790, 0, 170, 19);
panel_1.add(cSearch);
cSearch.addKeyListener(new CSearchKeyListener());
cSearch.setBounds(790, 20, 170, 23);
panel_1.add(label2);
label2.setText("Search by:");
label2.setBounds(662, 0, 127, 19);
panel_1.add(cSearchBy);
cSearchBy.addActionListener(new CSearchByActionListener());
cSearchBy.setBounds(662, 20, 127, 23);
cSearchBy.addItem("ID No");
cSearchBy.addItem("File No");
cSearchBy.addItem("Patient Name (EN)");
cSearchBy.addItem("Patient Name (ع)");
cSearchBy.addItem("Encounter No");
toolBar.setBounds(0, 0, 264, 45);
panel_1.add(toolBar);
toolBar.setFloatable(false);
toolBar.add(cRefresh);
toolBar.add(component5_1);
toolBar.add(cNew);
cNew.addActionListener(new CNewActionListener());
toolBar.add(component5_3);
toolBar.add(cModify);
cModify.addActionListener(new CModifyActionListener());
toolBar.add(component5);
toolBar.add(cMakeBill);
cMakeBill.setText("Make Bill");
cRefresh.addActionListener(new CRefreshActionListener());
cMakeBill.setIcon(SwingResourceManager.getIcon(PendingOInvoices.class, "/images/small/billmaker.png"));
cMakeBill.addActionListener(new CMakeBillActionListener());
toolBar.add(component5_2);
toolBar.add(cClose);
cClose.addActionListener(new CCloseActionListener());
panel_1.add(label1);
label1.setText("To Date:");
label1.setBounds(382, 0, 115, 19);
panel_1.add(cTDate);
cTDate.addTextListener(new CTDateTextListener());
cTDate.addKeyListener(new CTDateKeyListener());
cTDate.setBounds(382, 20, 115, 23);
getContentPane().add(table1);
table1.getJTable().addMouseListener(new table1JTableMouseListener());
table1.getJTable().addKeyListener(new Table1JTableKeyListener());
cSearch.setHorizontalAlignment(SwingConstants.CENTER);
panel_1.add(label);
label.setText("From Date:");
label.setBounds(266, 0, 115, 19);
panel_1.add(cFDate);
cFDate.setText("01/01/"+cTDate.getText().substring(7));
cFDate.addTextListener(new CFDateTextListener());
cFDate.addKeyListener(new CFDateKeyListener());
cFDate.setBounds(266, 20, 115, 23);
panel_1.add(label4);
label4.setText("Filtering Options:");
label4.setBounds(498, 0, 163, 19);
panel_1.add(cFilter);
cFilter.addActionListener(new CFilterActionListener());
cFilter.setBounds(498, 20, 163, 23);
cFilter.addItem("--- Choose ---");
cFilter.addItem("Guarantors Shares Only");
cFilter.addItem("Cash Patients Only");
cFilter.addItem("Patients Got Discount Only");
setWidths();
fillEncounters();
}
public void updateMe(String encno){
fillEncounters();
table1.getTable().requestFocus();
table1.getTable().setFocusCell(table1.search(encno, 1),1);
}
private void setWidths() {
model1.setColumnCount(9);
model1.setRowCount(0);
table1.getColumn(0).setPreferredWidth(75);
table1.getColumn(1).setPreferredWidth(90);
table1.getColumn(2).setPreferredWidth(350);
table1.getColumn(3).setPreferredWidth(80);
table1.getColumn(4).setPreferredWidth(80);
table1.getColumn(5).setPreferredWidth(80);
table1.getColumn(6).setPreferredWidth(80);
table1.getColumn(7).setPreferredWidth(80);
table1.getColumn(8).setPreferredWidth(20);
table1.getColumn(0).setHeaderValue("Date");
table1.getColumn(1).setHeaderValue("Encounter No");
table1.getColumn(2).setHeaderValue("Patient Name");
table1.getColumn(3).setHeaderValue("Total");
table1.getColumn(4).setHeaderValue("Guarantors");
table1.getColumn(5).setHeaderValue("Discount");
table1.getColumn(6).setHeaderValue("Paid");
table1.getColumn(7).setHeaderValue("Balance");
table1.getColumn(8).setHeaderValue("");
table1.setColumnType(0, JPVTable.DATE, null);
table1.setColumnType(1, JPVTable.DATE, null);
table1.setColumnType(2, JPVTable.TEXT, null);
table1.setColumnType(3, JPVTable.DOUBLE, null);
table1.setColumnType(4, JPVTable.DOUBLE, null);
table1.setColumnType(5, JPVTable.DOUBLE, null);
table1.setColumnType(6, JPVTable.DOUBLE, null);
table1.setColumnType(7, JPVTable.DOUBLE, null);
table1.setColumnType(8, JPVTable.BOOLEAN, null);
CTableConfig mc = new CTableConfig();
mc.newConfigureTable(table1,8,0,true);
table1.getTable().getColumnModel().getColumn(8).setHeaderRenderer(new CHGeneral(new MyItemListener()));
}
class MyItemListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
if (!(source instanceof AbstractButton)) return;
boolean checked = e.getStateChange() == ItemEvent.SELECTED;
int rows = model1.getRowCount();
for(int x = 0; x < rows; x++){
model1.setValueAt(checked,x,8);
}
}
}
private String getSearchColumn(){
if(cSearchBy.getSelectedIndex() == 0){
return "patients.PatID";
}else if(cSearchBy.getSelectedIndex() == 1){
return "encounters.Enc_Patient";
}else if(cSearchBy.getSelectedIndex() == 2){
return "concat(patients.PatFirst,' ', patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily)";
}else if(cSearchBy.getSelectedIndex() == 3){
return "concat(patients.PatFirstA,' ', patients.PatFatherA,' ',patients.PatMiddleA,' ',patients.PatFamilyA)";
}else if(cSearchBy.getSelectedIndex() == 4){
return "encounters.Enc_No";
}
return "";
}
private void fillEncounters(){
String currentValue = "";
int r = table1.getTable().getFocusRow();
cFDate.setFormat(2);
cTDate.setFormat(2);
String sql = "SELECT \n"
+"Date_Format(Enc_Date,'%d/%m/%Y'), \n"
+"encounters.Enc_No, \n"
+"CONCAT(' ',patients.PatFirst,' ',patients.PatFather,' ',patients.PatMiddle,' ',patients.PatFamily), \n"
+"FORMAT((Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED),2), \n"
+"FORMAT(Enc_Guarantor,2), \n"
+"FORMAT(Enc_Discount,2), \n"
+"FORMAT((Enc_Receipt-Enc_Payment),2), \n"
+"FORMAT(Enc_Balance,2), \n"
+""+Boolean.FALSE+", \n"
+"encounters.Enc_Patient, \n"
+"VERSION \n"
+"FROM \n"
+"encounters \n"
+"INNER JOIN encsummary ON encounters.Enc_No = encsummary.Enc_No \n"
+"INNER JOIN patients ON encounters.Enc_Patient = patients.PatNo \n"
+"WHERE Enc_Date Between '"+cFDate.getText()+"' AND '"+cTDate.getText()+"' AND Enc_Billed = 'false' \n"
+"AND (Enc_Clinics+Enc_Labs+Enc_Rads+Enc_MED) > 0 \n";
if(cFilter.getSelectedIndex() == 1){
sql+="and Enc_Guarantor > 0 \n";
}else if(cFilter.getSelectedIndex() == 2){
sql+="and Enc_Guarantor = 0 \n";
}else if(cFilter.getSelectedIndex() == 3){
sql+="and Enc_Discount > 0 \n";
}
if(cSearch.getText().trim().length() > 0){
sql+= "and "+getSearchColumn()+" LIKE '%"+cSearch.getText()+"%' \n";
}
sql+="Order By encounters.Enc_No DESC";
cFDate.setFormat(1);
cTDate.setFormat(1);
model1.setData(CDeclare.dataAccessor.getData(sql));
try{
currentValue = table1.getValueAt(r, 1).toString();
}catch(Exception ex){}
int i = table1.search(currentValue, 1);
table1.getTable().scrollRectToVisible(new Rectangle(table1.getTable().getCellRect(i, 1, true)));
table1.getTable().changeSelection(i, 1, false, false);
}
private class CSearchByActionListener implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
cSearchBy_actionPerformed(arg0);
}
}
private class table1JTableMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent arg0) {
table1JTable_mouseClicked(arg0);
}
}
private class CMakeBillActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cMakeBill_actionPerformed(e);
}
}
private class CSearchKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cSearch_keyReleased(e);
}
}
private class CTDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cTDate_keyReleased(e);
}
}
private class CRefreshActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cRefresh_actionPerformed(e);
}
}
private class CTDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cTDate_textValueChanged(e);
}
}
private class CCloseActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cClose_actionPerformed(e);
}
}
private class CFDateKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
cFDate_keyReleased(e);
}
}
private class CFDateTextListener implements TextListener {
public void textValueChanged(TextEvent e) {
cFDate_textValueChanged(e);
}
}
private class CNewActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cNew_actionPerformed(e);
}
}
private class CModifyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cModify_actionPerformed(e);
}
}
private class Table1JTableKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e) {
table1JTable_keyPressed(e);
}
}
private class CFilterActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cFilter_actionPerformed(e);
}
}
protected void cSearchBy_actionPerformed(ActionEvent arg0) {
if(cSearchBy.getSelectedIndex() == 3){
cSearch.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}else{
cSearch.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
}
cSearch.setText(null);
}
protected void table1JTable_mouseClicked(MouseEvent e) {
int c = table1.getTable().getSelectedColumn();
if(e.getClickCount() >= 2 && c != 8){
cModify_actionPerformed(null);
}
}
private void insertInvoice(){
double total = 0,guarantors = 0,grandtotal = 0;
CDate datg = new CDate();
String encno = "",invno = "",version = "";
for(int i = 0; i < model1.getRowCount();i++){
if(model1.getValueAt(i, 8).equals(Boolean.TRUE)){
if(datg.getFormat() != 1){
datg.setFormat(1);
}
encno = model1.getValueAt(i, 1).toString();
version = model1.getValueAt(i, 10).toString();
if(!CDeclare.SAMEVERSION("encounters","Enc_No",encno,version)){
return;
}
CDeclare.dataAccessor.UpdateDB("update encounters set VERSION = (VERSION+1) WHERE Enc_No = '"+encno+"'");
CDeclare.doubleValue.setValue(model1.getValueAt(i,3));
total = CDeclare.doubleValue.getDouble();
CDeclare.doubleValue.setValue(model1.getValueAt(i,4));
guarantors = CDeclare.doubleValue.getDouble();
grandtotal = total-guarantors;
invno = CDeclare.newNumber.getLastYearMonthNo(datg, "LastTemp");
datg.setFormat(2);
String sql = " Insert into invoice(Inv_No,Inv_Entry_Date,Inv_Kind,Inv_ClientKind,Inv_ClientSubKind,Inv_SubRefNo,Inv_Name,Inv_Date," +
"Inv_VatPercent,Inv_SubTotal,Inv_OthersTotal,Inv_Total,EMPIII) values (" +
"'" + invno + "'," +
"'" + CDeclare.getServerDateMySSQL() + "'," +
"'" + "S" + "'," +
"'" + "P" + "'," +
"'" + "OP" + "'," +
"'" + encno + "'," +
"'" + model1.getValueAt(i, 9) + "'," +
"'" + datg.getText() + "'," +
"'" + CDeclare.VAT + "'," +
"'" + total + "'," +
"'" + guarantors + "'," +
"'" + grandtotal + "'," +
"'" + CDeclare.EMPNO + "'" + ")";
CDeclare.dataAccessor.InsertDB(sql);
insertInvDetails(encno,invno);
}
}
}
private void insertInvDetails(String encno,String invno){
CCurrency vat = new CCurrency();
String invDetSql = "SELECT \n"
+"Sec_Account, \n"
+"Sec_Department, \n"
+"Ch_Kind, \n"
+"FORMAT((SUM(Ch_Total)/("+(1+CDeclare.VAT)+")),2), \n"
+"FORMAT(SUM(Ch_Total),2) \n"
+"FROM \n"
+"enccharges \n"
+"INNER JOIN medicalsections ON Ch_Section = Sec_No \n"
+"WHERE \n"
+"Ch_EncNo = '"+encno+"' \n"
+"GROUP BY Ch_Kind,Sec_Account,Sec_Department for update \n";
Vector<?> data = CDeclare.dataAccessor.getData(invDetSql);
for(int i = 0; i < data.size(); i++){
Vector<?> v = (Vector<?>) data.elementAt(i);
CDeclare.myDouble.setValue(v.elementAt(4));
CDeclare.doubleValue.setValue(v.elementAt(3));
vat.setDouble(vat.getDouble()+CDeclare.myDouble.getDouble()-CDeclare.doubleValue.getDouble());
String insSql = "Insert into invoicedetails(Inv_No,Inv_Account,Inv_Department,Inv_Kind,Inv_Total,Inv_TaxTotal) values (" +
"'" + invno + "'," +
"'" + v.elementAt(0) + "'," +
"'" + v.elementAt(1) + "'," +
"'" + v.elementAt(2) + "'," +
"'" + CDeclare.doubleValue.getDouble() + "'," +
"'" + CDeclare.myDouble.getDouble()+ "'" + ")";
CDeclare.dataAccessor.InsertDB(insSql);
}
CDeclare.dataAccessor.UpdateDB("update invoice set Inv_Vat = '"+vat.getDouble()+"' where Inv_No = '"+invno+"'");
String sqlUpdateEncounter = " Update encounters set \n" +
" Enc_Billed = 'true',\n" +
" Enc_Status = 'D',\n" +
" Enc_BillNo = '" + invno + "'\n " +
" where Enc_No = '" + encno + "'";
CDeclare.dataAccessor.UpdateDB(sqlUpdateEncounter);
}
protected void cMakeBill_actionPerformed(ActionEvent e) {
int option = (new CConfirms()).getSelection('S',"This operation will generate temporary invoices for selected encounters \n Are you sure ?!!!");
if(option != 0){
return;
}
CDeclare.dataAccessor.initAutoCommit();
CDeclare.dataAccessor.beginTransaction();
insertInvoice();
if(CDeclare.exCounter == 0){
CDeclare.dataAccessor.endTransaction();
fillEncounters();
}else{
CDeclare.dataAccessor.rollBack();
new CAlerts('D');
}
}
protected void cSearch_keyReleased(KeyEvent e) {
fillEncounters();
}
protected void cTDate_keyReleased(KeyEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cRefresh_actionPerformed(ActionEvent e) {
fillEncounters();
}
protected void cTDate_textValueChanged(TextEvent e) {
if(cTDate.getText().length() == 10){
fillEncounters();
}
}
protected void cClose_actionPerformed(ActionEvent e) {
dispose();
}
protected void cFDate_keyReleased(KeyEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cFDate_textValueChanged(TextEvent e) {
if(cFDate.getText().length() == 10){
fillEncounters();
}
}
protected void cNew_actionPerformed(ActionEvent e) {
NewEncounter newr = new NewEncounter(getTitle() + " - "+cNew.getText());
newr.insertMode();
newr.setOwner(this);
newr.setVisible(true);
}
protected void cModify_actionPerformed(ActionEvent e) {
int r = table1.getTable().getFocusRow();
String encno = model1.getValueAt(r,1).toString();
NewEncounter newr = new NewEncounter(getTitle() + " - "+cModify.getText());
newr.modifyMode();
newr.setOwner(this);
newr.fillEncounter(encno);
newr.setVisible(true);
}
protected void table1JTable_keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
e.consume();
cModify_actionPerformed(null);
}
}
protected void cFilter_actionPerformed(ActionEvent e) {
fillEncounters();
}
}
class MyOutBillingModel extends PVTableModel {
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int iRow, int iCol) {
try{
if(iCol == 8){
return true;
}
}catch(Exception ex){}
return false;
}
Your on the right track if you know what MVC is. You may also want to look at MVVM as it has the same goal. Let's break it down:
Model - simple classes with getter/setters and no logic or details about storage
View - classes or pages that display Model data in some organized way
Controller - the object that accepts actions from the View, manipulates Model, and transfers control to a new View (passing it a Model)
In general what we like to do is first "model" the data into classes that have no business logic, UI concepts or storage dependencies (like SQL). They are simple objects with getter/setter for data. Then the "view" classes/pages are designed so they know how to read those model objects and display them in whatever way makes sense. But the view does not know where/how those model objects are stored. The glue that puts the view and model together is the "controller", which is why it has that name. Typically the user interacts with the view to get/change data, and the view then invokes the controller with an "action" like "get-employee". The control is the only thing that knows what the action means and what to do. In the simple case, the controller will go get the data from the storage, and then decide on what the next view should be for the user. It takes the model object it loaded from storage, constructs the view, and passes the model to the view where it is rendered. The key point here is that the first view has no idea of what the controller is going to do and has no idea what the next view will be. That's all the business of the controller.
So in your case, you might have a few Employee Views like NewEmployee, EmployeeDetails, EmployeeListing. And then you might have a Model like Employee. You should be able to build these views with no SQL. That's how you know you are doing this right. Then, you introduce the Controller, like an EmployeeController. Then, you tie Button presses and click events in your Views to the action methods on the Controller. So you can add methods like this:
View listEmployees()
View createEmployee(Employee e)
View getEmployee(long id)
View deleteEmployee(long id)
Your Controller should then be the only component that interacts with storage, and then decides on what the "next" View should be. That's why it returns a View and not the Model. For instance, the method might look something like this:
public class EmployeeController {
. . .
public View listEmployees() {
List<Employee> employees = storage.getAllEmployees();
return new EmployeeListing(employees);
}
}
That's the basic concept and how the separation works. In most real MVC/MVVC frameworks, there is more sophistication around the mapping of actions and views.
Notice I also added a "storage" object so that even the Controller does not know that SQL is used. That will lead you to concepts like DAO which is how to abstract the actual storage details away from the rest of the app, if you want to.
Model View Controller (MVC) is a concept you may want to use. More about that in here: How to correctly implement swing-Please check the accepted answer in this link.
In your case, don't break the working code unless you have to...Remember that such a design change may cost more that its worth for a running system.
Start by separating all the SQL code into a separate package with interfaces and implementations. You can test those without the UI and put them aside.
Then I'd recommend making all the Swing classes another separate package. Do not call new to create and attach Listeners in the Swing classes. Instead, provide a mechanism for passing them in via constructors or setters. Inject those dependencies.
Model classes ought to represent the problem you're solving without a UI or database. See if they do.
Last have the controller package with classes that instantiate the listeners and views, gives the views the listeners they need, and fulfill the use cases by manipulating model and persistence objects.
That's MVC.
from what i read we should separate the logic from the design.
to be honest i don't know how to do that, or how to understand it.
The main reason (beyond the usual "cleaner code and architecture") why you want to do that and the principles behind can be explained best on an example.
Let's assume, you have a nice working desktop UI application. Now you want to create a web version of the very same application.
When the GUI application has placed all the business logic and all the DB accesses in the forms (or whatever the equivalent is), you got a problem. Because everything is coupled so tightly together, it is virtually impossible to re-use anything from the GUI application. So you start duplicating your code, and that's a real bad-bad. That way you end up with two code bases which have to be maintained.
In order to get the most out of the reusing game, you want to separate (at least) the UI from the underlying business logic. And while we're at it, it is also not such a bad idea to split the levels of abstraction once more and extracting the data model.
Now we can do something like this:
+-----------+
| Web UI |<<------+
+-----------+ |
| +-----------+ +------------+
+----->>| Biz Logic |<<---->>| Data Model |
| +-----------+ +------------+
+-----------+ |
| GUI |<<------+
+-----------+
To achieve that, you have to do certain things:
split the code accordingly to have independent (code) modules
remove all dependencies from right hand parts to left hand parts (ie. logic should not know anything about the UI details)
Methodical frameworks like MVC or MVVM or others can be considered as best-practice toolbelts to support you doing that at the interface between the logic and the UI parts. These concepts are proven and have matured over a long time. Strictly speaking, it is not required that you follow these concepts, but it is strongly recommended, as they not only help with architectural decisions but also and the make day-to-day coding work much easier, because of the existing framework implementations (again, that varies on what language etc. is used).
Here I have my terminal project, and inside the terminal, I can type "create", which will take me to the create prompt, where I can create a program. My problem right now is the fact that I can't get back to the Main class (Where I can select a command to run). I had the idea of trying to use the System.exit(0); but, as I didn't realise, it just kills the entire program. If anyone is able to help me, my file is below. I can post any other files if requested.
import java.util.*;
import java.io.*;
public class commandCreate {
boolean _active = true;
String _username = System.getProperty("user.name").toLowerCase();
String _os = System.getProperty("os.name").trim().toLowerCase();
String fileName, create, option;
public commandCreate() {
try {
while(_active) {
System.out.print(_username + "#" + _os + ":~/create$ ");
Scanner kbd = new Scanner(System.in);
String userLine = kbd.nextLine();
if(java.util.regex.Pattern.matches(".*\\S\\s+\\S.*", userLine)) {
Scanner read = new Scanner(userLine);
option = read.next();
fileName = read.next();
}
FileWriter create = new FileWriter(new File("Created Files/" + fileName + ".java"));
if(userLine.equals(option + " " + fileName)) {
if(option.equals("-a")) {
// Option = -a, creates standard file with main class.
create.write("public class " + fileName + " {\n");
create.write(" public static void main(String[] args) {\n");
create.write(" System.out.println(\"Welcome to your new program!\");\n");
create.write(" }\n");
create.write("}");
} else if(option.equals("-c")) {
// Option = -c , creates standard file with overloaded constructor & main class.
create.write("public class " + fileName + " {\n");
create.write(" public " + fileName + "() {\n");
create.write(" System.out.println(\"Welcome to your new program!\");\n");
create.write(" }\n");
create.write("\n");
create.write(" public static void main(String[] args) {\n");
create.write(" new " + fileName + "();\n");
create.write(" }\n");
create.write("}");
} else if(option.equals("-j")) {
// Option = -j, creates GUI within constructor w/ single JLabel.
create.write("import javax.swing.*;\n");
create.write("import java.awt.*;\n");
create.write("import java.awt.event.*;\n");
create.write("\n");
create.write("public class " + fileName + " extends JFrame {\n");
create.write(" private static final int HEIGHT = 50;\n");
create.write(" private static final int WIDTH = 400;\n");
create.write("\n");
create.write(" private JLabel welcomeJ;\n");
create.write("\n");
create.write(" public " + fileName + "() {\n");
create.write(" super(\"Welcome to your program - " + fileName + "\");\n");
create.write(" Container pane = getContentPane();\n");
create.write(" setLayout(new FlowLayout());\n");
create.write("\n");
create.write(" welcomeJ = new JLabel(\"Welcome To Your Program!\", SwingConstants.CENTER);\n");
create.write("\n");
create.write(" pane.add(welcomeJ);\n");
create.write("\n");
create.write(" setSize(WIDTH, HEIGHT);\n");
create.write(" setVisible(true);\n");
create.write(" setResizable(false);\n");
create.write(" setDefaultCloseOperation(EXIT_ON_CLOSE);\n");
create.write(" }\n");
create.write("\n");
create.write(" public static void main(String[] args) {\n");
create.write(" new " + fileName + "();\n");
create.write(" }\n");
create.write("}");
}
} else if(userLine.equalsIgnoreCase("help")) {
System.out.println("Commands");
System.out.println(" Syntax: [-option] [filename]");
System.out.println(" -a [filename] [Program: main class]");
System.out.println(" -c [filename] [Program: overloaded constructor, main class]");
System.out.println(" -j [filename] [Program: GUI: overloaded constructor, main class]");
} else if(userLine.equalsIgnoreCase("exit")) {
System.exit(0);
} else {
System.out.println("Error in syntax. Please review the \"help\" menu");
}
create.close();
}
} catch(IOException e) {
System.out.println("There was an error: " + e);
} catch(InputMismatchException ex) {
System.out.println("There was an error: " + ex);
}
}
public static void main(String[] args) {
new commandCreate();
}
}
The simple answer is to get the commandCreate constructor to return, or throw / propagate an exception. Indeed, I think this will happen already if the user enters an EOF.
(There are numerous other things wrong with your code, but it is probably better if you figure that out for yourself. I will point out however, that "commandCreate" or "CommandCreate" is a really poor choice for a class name. A class name is typically a noun.)
Your problem seems to be that you are stuck in an infinite while loop, there is no condition that sets the value _active to false.
} else if(userLine.equalsIgnoreCase("exit")) {
System.exit(0);
} else {
with
} else if(userLine.equalsIgnoreCase("exit")) {
_active = false;
} else {
That pretty much solves the problem of not being able exit. A return; statement would work equally well. I think Exceptions would be overkill in this particular instance.
On a side note (and something that most people seem to have pointed out), I would put the code in it's own method, run() for instance, and then use the call new commandCreate().run() in your main method.