국비교육(22-23)

24일차(1)/java(36) : JDBC 실습예제 (Friend 프레임)

서리/Seori 2022. 11. 8. 18:12

 

- 기존 실습예제를 활용해서 Frame 객체에서 관리 가능한 Friend 프레임/테이블 만들기!

 

 

[ 만들어야하는 클래스 ]

 

* FriendDTO : 필드, 생성자, getter/setter 세팅

* ORACLE에서 테이블 생성 : 테이블, 기본값 넣기. primary key 시퀀스 생성

  (ORACLE TO_CHAR 사용법 검색)

 

* FriendDBConnect : DB연결 객체

 - .jar 파일 사용

 

* FriendDAO : 한명의 회원정보를 관리하는 클래스

 - Connection 연결
 - sql문 작성 (? 넣어서)
 - pstmt에 sql문 담기
 - ?에 값 연결
 - 바뀐 row개수 리턴
 - finally문에서 입출력도구 닫기
 - 바뀐 row 개수로 성공여부 리턴

 

* FriendMain : MainClass, 프레임이 작동하는 메인메소드 생성
- 프레임, 테이블 UI 만들기
- DB 연결
- insert, update, delete, select (DAO 연동)

 

<FriendDto>

package test.dto;

import java.sql.Date;

public class FriendDto {
	//field 선언
	private int num;
	private String name;
	private String phone;
	private String birth;
	
	//디폴트 생성자
	public FriendDto() {};
	
	//인자 4개를 갖는 생성자
	public FriendDto(int num, String name, String phone, String birth) {
		super();
		this.num = num;
		this.name = name;
		this.phone = phone;
		this.birth = birth;
	}

	//각각의 field에 대한 getter,setter
	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getBirth() {
		return birth;
	}

	public void setBirth(String birth) {
		this.birth = birth;
	}	
}

- Date 타입은 사용이 까다로우므로 회원정보 중 birth도 String 타입으로 인식시킨다.



<FriendDao>

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.FriendDto;
import test.util.FriendDBConnect;

public class FriendDao {
	//멤버 한명의 정보를 저장,수정,삭제,열람하는 메소드
	//getList, getData 메소드
	
	//insert
	public boolean insert(FriendDto dto) {
		Connection frconn=null;
		PreparedStatement pstmt=null;		
		int rowCount=0;
		
		try {
			frconn=new FriendDBConnect().getFrConn();
			String sql="INSERT INTO friend"
					+" (num, name, phone, birth)"
					+" VALUES(member_seq.NEXTVAL, ?, ?, ?)";			
			pstmt=frconn.prepareStatement(sql);			
			pstmt.setString(1, dto.getName());
			pstmt.setString(2, dto.getPhone());
			pstmt.setString(3, dto.getBirth());
			rowCount=pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null) {pstmt.close();}
				if(frconn!=null) {frconn.close();}
			} catch (SQLException e) {}			
		}	
		if(rowCount>0) {
			return true;
		}else {
			return false;
		}
	}
	
	//update
	public boolean update(FriendDto dto) {
		Connection frconn=null;
		PreparedStatement pstmt=null;		
		int rowCount=0;
		
		try {
			frconn=new FriendDBConnect().getFrConn();
			String sql="UPDATE friend"
					+" SET name=?, phone=?, birth=?"
					+" WHERE num=?";			
			pstmt=frconn.prepareStatement(sql);			
			pstmt.setString(1, dto.getName());
			pstmt.setString(2, dto.getPhone());
			pstmt.setString(3, dto.getBirth());
			pstmt.setInt(4, dto.getNum());
			rowCount=pstmt.executeUpdate();			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null) {pstmt.close();}
				if(frconn!=null) {frconn.close();}
			} catch (SQLException e) {}			
		}	
		if(rowCount>0) {
			return true;
		}else {
			return false;
		}
	}	
	
	//delete
	public boolean delete(int num) {
		Connection frconn=null;
		PreparedStatement pstmt=null;		
		int rowCount=0;
		
		try {
			frconn=new FriendDBConnect().getFrConn();
			String sql="DELETE FROM friend"
					+" WHERE num=?";			
			pstmt=frconn.prepareStatement(sql);
			pstmt.setInt(1, num);
			rowCount=pstmt.executeUpdate();			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(pstmt!=null) {pstmt.close();}
				if(frconn!=null) {frconn.close();}
			} catch (SQLException e) {}			
		}	
		if(rowCount>0) {
			return true;
		}else {
			return false;
		}
	}

	//getList(select 전체)
	public List<FriendDto> getList() {
		List<FriendDto> list=new ArrayList<>();
		
		Connection frconn=null;
		PreparedStatement pstmt=null;		
		ResultSet result=null;
		
		try {
			frconn=new FriendDBConnect().getFrConn();
			String sql="SELECT num, name, phone, TO_CHAR(birth)"					
					+" FROM friend"
					+" ORDER BY num ASC";			
			pstmt=frconn.prepareStatement(sql);			
			result=pstmt.executeQuery();
			while(result.next()) {
				FriendDto dto=new FriendDto();
				dto.setNum(result.getInt("NUM"));
				dto.setName(result.getString("NAME"));
				dto.setPhone(result.getString("PHONE"));
				dto.setBirth(result.getString("TO_CHAR(BIRTH)"));
				list.add(dto);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(result!=null) {result.close();}
				if(pstmt!=null) {pstmt.close();}
				if(frconn!=null) {frconn.close();}
			} catch (SQLException e) {}			
		}
		return list;
	}
		
	//getData(select 일부만)
	public FriendDto getData(int num) {		
		FriendDto dto=null;
		
		Connection frconn=null;
		PreparedStatement pstmt=null;		
		ResultSet result=null;
		
		try {
			frconn=new FriendDBConnect().getFrConn();
			String sql="SELECT num, name, phone, TO_CHAR(birth)"					
					+" FROM friend"
					+" WHERE num=?"
					+" ORDER BY num ASC";			
			pstmt=frconn.prepareStatement(sql);
			pstmt.setInt(1, num);
			result=pstmt.executeQuery();
			while(result.next()) {
				dto=new FriendDto();
				dto.setNum(result.getInt("num"));
				dto.setName(result.getString("name"));
				dto.setPhone(result.getString("phone"));
				dto.setBirth(result.getString("TO_CHAR(birth)"));				
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(result!=null) {result.close();}
				if(pstmt!=null) {pstmt.close();}
				if(frconn!=null) {frconn.close();}
			} catch (SQLException e) {}			
		}
		return dto;
	}	
}

- 5개의 메소드 생성. insert, update, delete, getList, getData.

- 필요시 FriendDao(). 으로 호출해서 사용!

 

- SELECT문에서 TO_CHAR을 적용하여 birth 칼럼도 String 타입으로 반환한다.

 

 

<FriendDBConnect> 

package test.util;

import java.sql.Connection;
import java.sql.DriverManager;

public class FriendDBConnect {
	//필드
	Connection frConn;
		
	//생성자
	public FriendDBConnect() {
		try { 
			Class.forName("oracle.jdbc.driver.OracleDriver");
			String url="jdbc:oracle:thin:@localhost:1521:xe";
			frConn=DriverManager.getConnection(url, "scott", "tiger");
			System.out.println("Oracle DB에 접속했습니다.");
		}		
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//메소드, 리턴값
	public Connection getFrConn() {
		return frConn;
	}
}

- Oracle DB에 접속하고, 참조값을 리턴해준다.

 

 

<FriendFrame>

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.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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.FriendDao;
import test.dto.FriendDto;

public class FriendFrame extends JFrame 
		implements ActionListener, PropertyChangeListener {
	
	//필드
	JTextField inputName, inputPhone, inputBirth;
	JTable table; 
	DefaultTableModel model;
	
	//생성자
	public FriendFrame() {
		setLayout(new BorderLayout());
	      
		JLabel label1=new JLabel("이름");
		inputName=new JTextField(10);	      
		JLabel label2=new JLabel("전화번호");
		inputPhone=new JTextField(10);
		JLabel label3=new JLabel("생년월일");
		inputBirth=new JTextField(10);	    
	      
	    JButton saveBtn=new JButton("저장");
	    saveBtn.setActionCommand("save");	    
	    JButton deleteBtn=new JButton("삭제");
	    deleteBtn.setActionCommand("delete");
	    
	    JLabel label4=new JLabel("생년월일은 'YYYY-MM-DD'로 입력해주세요.");
		
	    JPanel panel=new JPanel();
	    panel.add(label1);
	    panel.add(inputName);
	    panel.add(label2);
	    panel.add(inputPhone);
	    panel.add(label3);
	    panel.add(inputBirth);
	    panel.add(saveBtn);
	    panel.add(deleteBtn);
	    panel.add(label4);
	    add(panel,BorderLayout.NORTH);
		
	    table=new JTable();
	    String[] colNames= {"번호","이름","전화번호","생년월일"};
	    
	    model=new DefaultTableModel(colNames, 0) {
	    	@Override
	    	public boolean isCellEditable(int row, int column) {
	    		if(column==0) {
	    			return false;
	    		}else {
	    			return true;
	    		}
	    	}
	    };
	    
	    table.setModel(model);
	    JScrollPane scroll=new JScrollPane(table);
	    add(scroll, BorderLayout.CENTER);
	    
	    //버튼에 리스너
	    saveBtn.addActionListener(this);
	    deleteBtn.addActionListener(this);
	    displayFriend();
	    
	    table.addPropertyChangeListener(this);
	}
	
	public void displayFriend() {
		model.setRowCount(0);
		FriendDao dao=new FriendDao();		
		List<FriendDto> list=dao.getList();		
		for(FriendDto tmp:list) {
			Object[] row= {tmp.getNum(), tmp.getName(), tmp.getPhone(), tmp.getBirth()};
			model.addRow(row);
		}		
	}
	
	
	public static void main(String[] args) {
		FriendFrame fr=new FriendFrame();
		fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fr.setBounds(100, 100, 800, 500);
		fr.setVisible(true);		
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		String command=e.getActionCommand();
		if(command.equals("save")) {			
			String name=inputName.getText();
			String phone=inputPhone.getText();
			String birth=inputBirth.getText();			
			
			FriendDto dto=new FriendDto();			
			dto.setName(name);
			dto.setPhone(phone);
			dto.setBirth(birth);
			
			FriendDao dao=new FriendDao();
			boolean isSuccess=dao.insert(dto);
				if (isSuccess) {			
					displayFriend();
					JOptionPane.showMessageDialog(this, name+"의 정보를 추가했습니다.");
				}else {
					JOptionPane.showMessageDialog(this, "친구정보 추가에 실패했습니다.");
				}
		}else if(command.equals("delete")){
			int rowIndex=table.getSelectedRow();			
			if(rowIndex==-1) {
				JOptionPane.showMessageDialog(this, "삭제할 친구를 선택해주세요!");
				return;
			}
			int result=JOptionPane.showConfirmDialog(this, "선택된 친구를 삭제하시겠습니까?");
			if(result==JOptionPane.YES_OPTION) {
				int num=(int)model.getValueAt(rowIndex, 0);
				new FriendDao().delete(num);								
				displayFriend();				
			}
		}		
	}

	//table에 특정 이벤트가 발생했을 때 호출
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if(evt.getPropertyName().equals("tableCellEditor") && !table.isEditing()){
			int selectedIndex=table.getSelectedRow();
			int num=(int)model.getValueAt(selectedIndex, 0);
			String name=(String)model.getValueAt(selectedIndex, 1);
			String phone=(String)model.getValueAt(selectedIndex, 2);
			String birth=(String)model.getValueAt(selectedIndex, 3);
			FriendDto dto=new FriendDto(num, name, phone, birth);
			new FriendDao().update(dto);
			table.clearSelection();			
		}		
	}
}

- Frame 틀, Table UI와 각각의 Label, 데이터를 저장할 Model 만들기

- ActionPerformed로 저장, 삭제 버튼 클릭시의 기능을 추가

- PropertyChange를 사용해서 테이블에 수정사항이 있을 때 정보를 업데이트하는 내용 추가

 

 

 

- 데이터 저장, 저장한 데이터 수정 가능. DB에도 즉시 반영!