본문 바로가기

Languages/JAVA

[JAVA] JFrame 사용해보기 #2 - DB 연동 (DTO, DAO)

저번시간에 JFrame의 기초를 알아보았습니다. 이번시간에는 JFram에 Dao, Dto를 사용해서 DB와 연동을 해봅시다.

 

저번 게시글 링크 -> [JAVA] JFrame 사용해보기 #1 - 예제로 다양한 기능 알아보기

 

[JAVA] JFrame 사용해보기 #1 - 예제로 다양한 기능 알아보기

오늘은 JFrame 사용해봅시다. 다양한 예제를 보면서 기능을 알아가봅시다. 자바에서 JFrame은 GUI를 제공해줍니다. 이렇게 창안에서 자기가 원하는 다양한 기능들을 만들 수 있습니다. JFrame의 3가지

e-you.tistory.com

 

Dto와 Dao의 자세한 설명과 예제는 여기를 참고해주세요!


 

기능

  1. 이름, 직책을 텍스트 필드에 적고 추가 버튼 누르면 추가
  2. 삭제하고싶은 내용을 클릭해서 삭제 버튼을 누르면 삭제
  3. 변경하고 싶은 내용을 클릭해서 변경하면 변경됨
  4. 일정시간마다 내용 새로고침

위 기능을 구현해봅시다!


DBConnect.java

package test.util;

import java.sql.Connection;
import java.sql.DriverManager;
/*
 * 객체를 생성해서 메소드를 호출하면 Connection 객체를 리턴하는 객체를 생성할 클래스 설계하기
 */

public class DBConnect {
	//Connection 객체의 참조값을 담을 필드 선언
	private Connection conn;
	
	//생성자에서 Connection 객체를 얻어오는 작업을 한다.
	public DBConnect() {
	      try {
	    	 //오라클 드라이버 클래스 로딩(OracleDriver 클래스를 사용할 준비를 한다)
	         Class.forName("oracle.jdbc.driver.OracleDriver");
	         //접속할 DB 의 정보
	         String url="jdbc:oracle:thin:@localhost:1521:xe";
	         //DB 연결 객체의 참조값 얻어와서 필드에 담기
	         conn=DriverManager.getConnection(url, "scott", "tiger");
	         //예외가 발생하지 않고 여기까지 실행순서가 진행이되면 접속 성공이다.
	         System.out.println("Oracle DB 접속 성공!");
	         
	      }catch(Exception e){
	      
	      }
	}
	
	//Connection 객체를 리턴하는 메소드
	public Connection getConn() {
		return conn;
	}
	
	
}

CompanyDto.java

package test.dto;

public class CompanyDto {
	private int empno;
	private String ename;
	private String job;
	private String hiredate;
	
	
	public CompanyDto() {
		super();
	}



	public CompanyDto(int empno, String ename, String job, String hiredate) {
		super();
		this.empno = empno;
		this.ename = ename;
		this.job = job;
		this.hiredate = hiredate;
	}


	public int getEmpno() {
		return empno;
	}


	public void setEmpno(int empno) {
		this.empno = empno;
	}


	public String getEname() {
		return ename;
	}


	public void setEname(String ename) {
		this.ename = ename;
	}


	public String getJob() {
		return job;
	}


	public void setJob(String job) {
		this.job = job;
	}


	public String getHiredate() {
		return hiredate;
	}


	public void setHiredate(String hiredate) {
		this.hiredate = hiredate;
	}
	
	
	
	
}

CompanyDao.java

package test.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import test.dto.CompanyDto;
import test.util.DBConnect;

public class CompanyDao {
	
	public boolean insert(CompanyDto dto) {
		//필요한 객체를 담을 지역 변수 미리 만들기
		Connection conn = null;
		PreparedStatement pstmt = null;
		int flag = 0;
		try {
			//Connection 객체의 참조값 얻어오기 
			conn = new DBConnect().getConn();
			//실행할 sql 문의 뼈대 미리 준비하기
			String sql = "INSERT INTO company"
					+ " (empno,ename,job,hiredate)"
					+ " VALUES(company_seq.NEXTVAL,?,?,SYSDATE)";
			//PreparedStatement 객체의 참조값 얻어오기
			pstmt = conn.prepareStatement(sql);
			//? 에 필요한값 바인딩하기 
			pstmt.setString(1, dto.getEname());
			pstmt.setString(2, dto.getJob());
			//sql 문 실행하기 (INSERT, UPDATE, DELETE)
			flag = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
			}
		}
		if (flag > 0) {
			//성공
			return true;
		} else {
			//실패
			return false;
		}
	}
	
	public boolean update(CompanyDto dto) {
		//필요한 객체를 담을 지역 변수 미리 만들기
		Connection conn = null;
		PreparedStatement pstmt = null;
		int flag = 0;
		try {
			//Connection 객체의 참조값 얻어오기 
			conn = new DBConnect().getConn();
			//실행할 sql 문의 뼈대 미리 준비하기
			String sql = "UPDATE Company"
					+" SET ename=?, job=?"
					+" WHERE empno=?";
			//PreparedStatement 객체의 참조값 얻어오기
			pstmt = conn.prepareStatement(sql);
			//? 에 필요한값 바인딩하기 
			pstmt.setString(1, dto.getEname());
			pstmt.setString(2, dto.getJob());
			pstmt.setInt(3, dto.getEmpno());
			//sql 문 실행하기 (INSERT, UPDATE, DELETE)
			flag = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
			}
		}
		if (flag > 0) {
			//성공
			return true;
		} else {
			//실패
			return false;
		}
	}
	
	public boolean delete(CompanyDto dto) {
		//필요한 객체를 담을 지역 변수 미리 만들기
		Connection conn = null;
		PreparedStatement pstmt = null;
		int flag = 0;
		try {
			//Connection 객체의 참조값 얻어오기 
			conn = new DBConnect().getConn();
			//실행할 sql 문의 뼈대 미리 준비하기
			String sql = "DELETE FROM Company"
					+" WHERE empno=?";
			//PreparedStatement 객체의 참조값 얻어오기
			pstmt = conn.prepareStatement(sql);
			//? 에 필요한값 바인딩하기 
			pstmt.setInt(1, dto.getEmpno());
			//sql 문 실행하기 (INSERT, UPDATE, DELETE)
			flag = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
			}
		}
		if (flag > 0) {
			//성공
			return true;
		} else {
			//실패
			return false;
		}
	}
	
	public CompanyDto getData(int empno) {
		//필요한 객체를 담을 지역 변수 미리 만들기
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		CompanyDto dto = null;
		try {
			//Connection 객체의 참조값 얻어오기 
			conn = new DBConnect().getConn();
			//실행할 sql 문의 뼈대 미리 준비하기
			String sql = "SELECT ename, job, TO_CHAR(hiredate,'YYYY.mm.dd') as hiredate"
					+" FROM Company"
					+ " WHERE empno = ?";
			//PreparedStatement 객체의 참조값 얻어오기
			pstmt = conn.prepareStatement(sql);
			//? 에 필요한값 바인딩하기 
			pstmt.setInt(1, empno);
			//select 문 수행하고 결과를 ResultSet 으로 받아오기 
			rs = pstmt.executeQuery();
			if (rs.next()) {
				//cursor 가 위치한 곳의 칼럼 데이터를 빼오기
				dto = new CompanyDto();
				dto.setEmpno(empno);
				dto.setEname(rs.getString("ename"));
				dto.setJob(rs.getString("job"));
				dto.setHiredate(rs.getString("hiredate"));
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
			}
		}
		return dto;
	}
	
	public List<CompanyDto> getList(){
		//필요한 객체를 담을 지역 변수 미리 만들기
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		List<CompanyDto> list = new ArrayList<>();
		
		try {
			//Connection 객체의 참조값 얻어오기 
			conn = new DBConnect().getConn();
			//실행할 sql 문의 뼈대 미리 준비하기
			String sql = "SELECT empno, ename, job, TO_CHAR(hiredate,'YYYY.mm.dd') as hiredate"
					+" FROM Company";
			//PreparedStatement 객체의 참조값 얻어오기
			pstmt = conn.prepareStatement(sql);
			//? 에 필요한값 바인딩하기 

			//select 문 수행하고 결과를 ResultSet 으로 받아오기 
			rs = pstmt.executeQuery();
			while (rs.next()) {
				//cursor 가 위치한 곳의 칼럼 데이터를 빼오기 
				CompanyDto dto = new CompanyDto();
				dto.setEmpno(rs.getInt("empno"));
				dto.setEname(rs.getString("ename"));
				dto.setJob(rs.getString("job"));
				dto.setHiredate(rs.getString("hiredate"));
				list.add(dto);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
			}
		}
		return list;
	}
	
}

이제 main 을 봅시다!

 

package test.frame;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import test.dao.CompanyDao;
import test.dto.CompanyDto;


public class CompanyFrame extends JFrame implements ActionListener, PropertyChangeListener{

	JTextField inputEname,inputJob;
	JTable table;
	DefaultTableModel model;
	List<CompanyDto> companys;
	
	public CompanyFrame(){
		 setTitle("사원정보");
		 setSize(800, 500);
	      setLocation(100, 100);
	      setDefaultCloseOperation(EXIT_ON_CLOSE);
	      //BorderLayout 객체 전달하기
	      setLayout(new BorderLayout());
	      
	      //필요한 UI 객체를 생성해서 
	      JLabel labelName=new JLabel("이름");
	      JLabel labelAddr=new JLabel("직책");
	      inputEname=new JTextField(10);
	      inputJob=new JTextField(10);
	      JButton addBtn=new JButton("추가");
	      JButton deleteBtn=new JButton("삭제");
	      JButton refreshBtn = new JButton("새로고침");
	      
	      //페널에 추가한 후 
	      JPanel topPanel=new JPanel();
	      topPanel.add(labelName);
	      topPanel.add(inputEname);
	      topPanel.add(labelAddr);
	      topPanel.add(inputJob);
	      topPanel.add(addBtn);
	      topPanel.add(deleteBtn);
	      topPanel.add(refreshBtn);
	      //프레임의 상단에 페널을 배치한다.
	      add(topPanel, BorderLayout.NORTH);
	      //버튼에 리스너 등록
	      addBtn.addActionListener(this);
	      deleteBtn.addActionListener(this);
	      refreshBtn.addActionListener(this);
	      //버튼에 action command 설정
	      addBtn.setActionCommand("add");
	      deleteBtn.setActionCommand("delete");
	      refreshBtn.setActionCommand("refresh");
	      
	      //표형식으로 정보를 출력하기 위한 JTable
	      table=new JTable();
	      //테이블의 칼럼명을 String[] 로 준비하기
	      String[] colNames= {"사원 번호", "사원 이름", "직책", "입사일"};
	      //테이블에 출력할 데이터를 가지고 있는 DefaultTableModel
	      model=new DefaultTableModel(colNames, 0) {
	    	  //인자로 전달되는 행(row), 열(column) 수정 가능 여부를 리턴하는 메소드
	    	  @Override
	    	public boolean isCellEditable(int row, int column) {
	    		  //0번 칼럼만 수정 불가능하도록 false를 리턴해주고
	    		if(column == 0 || column==3) {
	    			return false;
	    		}else {
	    			//나머지는 모두 수정 가능하도록 true를 리턴한다.
	    			return true;
	    		}
	    		
	    	}
	      };
	      //모델을 테이블에 연결
	      table.setModel(model);
	      //스크롤이 가능하도록 
	      JScrollPane sc=new JScrollPane(table);
	      //프레임의 가운데에 배치
	      add(sc, BorderLayout.CENTER);
	      //테이블에 회원 목록 출력하기
	      showMembers();
	      
	      //테이블 셀에 수정작업이 일어났는지 감시할 리스너 등록 
	      table.addPropertyChangeListener(this);
	      
	      autoRefresh();
	      
	      setVisible(true);
	}
	
	public static void main(String[] args) {
		new CompanyFrame();
	}

	public void showMembers() {
	      //DB 에서 회원 목록을 얻어와서 
	      companys=new CompanyDao().getList();
	      for(CompanyDto tmp:companys) {
	         //테이블 row 에 출력할 데이터를 순서대로 담은 Object[] 객체를 준비해서 
	         Object[] row= {tmp.getEmpno(),tmp.getEname(),tmp.getJob(),tmp.getHiredate()};
	         //모델에 추가한다. 
	         model.addRow(row);
	      }
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("add")) {
			addAction();
		}else if(e.getActionCommand().equals("delete")) {
			deleteAction();
		}else if(e.getActionCommand().equals("refresh")) {
			model.setRowCount(0);
			showMembers();
		}
		
	}

	private void deleteAction() {
	      //선택된 row 의 인덱스를 얻어와서 
	      int index=table.getSelectedRow();
	      if(index == -1)return;
	      //DB 에서 삭제하고
	      CompanyDto dto = new CompanyDto();
	      dto.setEmpno(companys.get(index).getEmpno());
	      new CompanyDao().delete(dto);
	      //다시 출력
	      model.setRowCount(0);
	      showMembers();
		
	}

	private void addAction() {
	      //1. 입력한 이름과 주소를 읽어온다.
	      String ename=inputEname.getText();
	      String job=inputJob.getText();
	      //2. DB 에 저장한다.
	      CompanyDto dto=new CompanyDto();
	      dto.setEname(ename);
	      dto.setJob(job);
	      //작업의 성공여부를 리턴 받는다. 
	      boolean isSuccess=new CompanyDao().insert(dto);
	      
	      if(isSuccess) {
	         JOptionPane.showMessageDialog(this, "저장 했습니다.");
	         //행의 갯수를 강제로 0 로 만들고 
	         model.setRowCount(0);
	         //다시 출력하기
	         showMembers();
	      }else {
	         JOptionPane.showMessageDialog(this, "저장 실패!");
	      }
		
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
	      System.out.println("propertyChange()");
	      System.out.println(evt.getPropertyName());
	      if(evt.getPropertyName().equals("tableCellEditor")) {
	         //선택된 row 의 index 를 얻어와서 
	         int index=table.getSelectedRow();
	         //인덱스에 해당하는 model 에서 입력된 이름과 주소를 읽어온다. 
	         int empno=(int)model.getValueAt(index, 0); //0번째 인덱스의 번호를 읽어온다. 
	         String ename=(String)model.getValueAt(index, 1); //1번째 인덱스의 이름을 읽어온다.
	         String job=(String)model.getValueAt(index, 2); //2번째 인덱스의 주소를 읽어온다.
	         String hiredate=(String)model.getValueAt(index, 3); //3번째 인덱스의 입사일을 읽어온다.
	         //DB 에 수정 반영
	         CompanyDto dto=new CompanyDto(empno,ename,job,hiredate);
	         new CompanyDao().update(dto);
	      }
		
	}
	
	//주기적으로 refresh 하는 메소드
	public void autoRefresh() {
		new Thread() {
			@Override
			public void run() {
				while(true) {
					
					try {
						Thread.sleep(30000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					model.setRowCount(0);
					showMembers();
				}
			}
		}.start();
	}
}

구현 방법

  • showMembers() : DB에서 회원 목록 얻어옴
  • actionPerformed(ActionEvent e) : 버튼 액션을 제어함
  • addAction() : 데이터를 DB에 추가, 성공하면 저장했습니다. 라는 Dialog 띄워줌
  • deleteAction() : 선택한 행 데이터를 삭제
  • propertyChange(PropertyChangeEvent evt) : 텍스트 변경을 감지한다. 변경되면 DB내용을 업데이트해줌 , PropertyChangeListener를 implements해주어야한다.
  • autoRefresh() : 주기적으로 새로고침을 해주는 메소드