2022-02-09 JDBC

GGAE99·2022년 2월 9일
0

진도

목록 보기
20/43

오늘은 데이터베이스와 자바를 연동하는 방법을 배워봤다.

JDBC

  • JDBC
    JDBC는 자바에서 데이터베이스에 접속할 수 있도록 해주는 기능을 제공하는 자바 API이다.
    JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트할 수 있도록 기능을 제공한다.

SQL - 연동할 데이터 만들기

오늘 배운 내용은 이전에 배운 이론적인 느낌보다는 실제로 어떻게 해야하는지 알려주는 것 같았다.
먼저 데이터베이스를 먼저 키고 자바가 접속할 사용자계정을 하나 만들어준다.

CREATE USER JDBC IDENTIFIED BY 1234;
GRANT CONNECT, RESOURCE TO JDBC;

그리고 SQL의 JDBC계정에서 테이블을 만들어준다.
오늘은 필자의 코드가 상당히 길거다...ㅜ

CREATE TABLE MEMBER(
    MEMBER_NO       NUMBER          PRIMARY KEY,        --회원번호
    MEMBER_ID       VARCHAR2(20)    UNIQUE NOT NULL,    --아이디
    MEMBER_NAME     VARCHAR2(20)    NOT NULL,           --이름
    GENDER          CHAR(3) CHECK(GENDER IN ('남','여')),  -- 성별
    ENROLL_DATE     DATE                                --기입일
);

이게 알아보기 쉽게 줄인다고 줄인 코드이다.
테이블에 값도 넣어보자.

CREATE SEQUENCE MEMBER_SEQ;                             
--회원번호를 자동으로 채변할 시퀀스

INSERT INTO MEMBER VALUES(MEMBER_SEQ.NEXTVAL,'user01','유저1','남',SYSDATE);
INSERT INTO MEMBER VALUES(MEMBER_SEQ.NEXTVAL,'user02','유저2','여',SYSDATE);
                                        
SELECT * FROM MEMBER;
COMMIT;

마지막에 COMMIT을 반드시 해주어야한다. 안그러면 나중에 java에서 인식을 못한다.
SQL에서 할건 끝났다. java로 넘어가보자.

Java 설정

일단 java하고 SQL을 연동하기 위해서 해야할 설정이 좀 있다.
기본적으로 java와 SQL이 사용하는 한글의 타입이 다르다. 타입을 통일해주자.
이클립스의 window -> general -> workspace (클릭)-> text file encoding에서 타입을 UTF-8로 변경해준다. 이 타입이 SQL에서 쓰는 한글타입인데, SQL거로 통일해주자.
이거 안해주면 나중에 한글이 깨진다.
다음은 window -> general -> eidtors -> text eidtors -> spelling(클릭) -> encoding에서 마찬가지로 타입을 UTF-8로 변경해준다.

다음은 sql파일은 자바에 넣어주는 것을 해야한다.
SQL과 연동할 패키지를 우클릭하고 properties로 들어가 java build path 항목의 libraries로 들어가준다. 그리고 add external jars (외부 jars파일 넣기)를 해서 자신의 sql과 맞는 파일의 jar파일을 넣어준다. 이건 인터넷보고 찾는게 빠르겠다..! 여기는 그냥 간단하게만! 끝!

Java - SQL과 연동하여 만들기

일단 패키지를 네개 만들어주자.

controller : 실행될 코드를 넣어줄 패키지
dao : db와 연동하여 값을 받아오는 함수를 만들어줄 패키지
run : main함수가 들어있는 직접적인 실행을 하게해주는 패키지
vo : 테이블값을 넣어줄 패키지

모든 프로젝트마다 사용해야하는 패키지의 수는 다를것이다. 이번에는 그냥 필자가 짠 걸 보여주는 것 이다. 패키지의 이름도 알아보기 쉽게 만들어주자.

먼저 vo패키지부터 만져보자. vo패키지는 아까 SQL에서 만들어줬던 테이블의 쿼리를 변수로 가지고있도록 만들어주도록 하자.

public class Member {
	private int memberNO;
    private String memberId;
	private String memberName;
	private char gender;
	private Date enrollDate;
}

public Member(int memberNO, String memberId, String memberName,char gender, Date enrollDate) {
		super();
		this.memberNO = memberNO;
		this.memberId = memberId;
		this.memberName = memberName;
		this.gender = gender;
		this.enrollDate = enrollDate;
	}

매개변수 생성자까지만 작성하겠다.
getter setter는 너무 길어지니 생략쓰. 만들어는 뒀다.

이번에 작성할 프로그램은 회원을 관리하는 프로그램이다.
기본적인 틀을 만들어놨다.

public void main() {
		while(true) {
			System.out.println("----- 회원 관리 프로그램 -----");
			System.out.println("1. 전체회원조회");
			System.out.println("2. 회원1명조회");
			System.out.println("3. 회원정보등록");
			System.out.println("4. 회원정보수정");
			System.out.println("5. 회원삭제");
			System.out.println("0. 프로그램 종료");
			System.out.print("선택 > ");
			int sel = sc.nextInt();
			
			switch(sel) {
			case 1:
				selectAllMember();
				break;
			case 2:
				selectOneMember();
				break;
			case 3:
				break;
			case 4:
				break;
			case 5:
				break;
			case 0:
				System.out.println("프로그램을 종료합니다.");
				return;
			default:
				System.out.println("잘못입력하셨습니다.");
				break;
			}
		}
	}

그렇다. 필자는 1번이랑 2번까지밖에 안했다. 오늘은 1,2번만 진행할거다.

먼저 controller 메소드의 변수이다.

public class MemberController {
	private Scanner sc;
	private MemberDao dao;

	public MemberController() {
		super();
		sc = new Scanner(System.in);
		dao = new MemberDao();
	}

생성자까지 만들었다.

전체회원을 조회하는 메소드다.
이 메소드는 controller 패키지의 클래스에 작성한다.

// 전체회원정보를 출력하는 메소드
	public void selectAllMember() {
		//dao를 통해서 전체회원정보를 받아오면 됨
		ArrayList<Member> list = dao.selectAllMember();
		System.out.println("회원번호\t아이디\t이름\t성별\t가입일");
		System.out.println("--------------------------------------------------");
		for(Member m : list) {
			System.out.println(m.getMemberNo()+"\t"+m.getMemberId()+"\t"+
            m.getMemberName()+"\t""+m.getGender()+"\t"+m.getEnrollDate());
		}
		//db에서 필요한 데이터를 조회해왔으니 출력
	}//selectAllMember end

중간에 보면 dao.selectAllMember라는 메소드가 들어가있다. dao패키지의 MemberDao라는 클래스를 dao라고 정의해놓았기 때문에 사용이 가능하다. 이걸로 알 수 있듯이, 필자는 dao패키지에 selectAllMember라는 메소드를 생성해놓았고, controller의 클래스는 이를 참조한다.

바로 dao 패키지의 코드를 보자.

// 데이터베이스의 Member테이블을 조작할때 사용하는 클래스
// DAO : Data Access Object
public class MemberDao {
	public ArrayList<Member> selectAllMember() {
		//데이터베이스 접속해서 데이터를 가져오는 코드
		// 1. 필요한 변수를 선언 (미리 선언하는 이유는 try~catch 후 자원반환을 위해 미리선언)
		Connection conn = null;	//DBMS와 연결을 담당하는 객체
		Statement stmt = null;	//query를 전송하고 결과를 받아오는 객체
		// 데이터베이스에서 수행할 쿼리가 select인 경우 ResultSet 객체 생성
		// 데이터베이스에서 수행할 쿼리가 insert/update/delete인경우 int변수 생성
		ResultSet rset = null;	//select 수행결과를 저장하는 객체
		
		//전체회원정보를 저장할 변수
		ArrayList<Member> list = new ArrayList<Member>();
		// 수행할 쿼리
		String query = "select * from member";
		
		try {
			//2. 사용할 DBMS드리이버 등록(ojdbc6.jar에서 제공하는 클래스위치를 지정)
			// ojdbc라이브러리를 등록하지않았으면 여기서 에럭 나옴
			Class.forName("oracle.jdbc.driver.OracleDriver");
            
			//3. 등록된 클래스를 이용해서 DB연결 (연결 성공하면 connection객체 리턴, / 실패하면 null 리턴)
			conn = DriverManager.getConnection
					("jdbc:oracle:thin:@127.0.0.1:1521:xe","jdbc","1234");
                    
			//4. 쿼리문을 실행하고 결과를 받아오는 statement객체 생성
			stmt = conn.createStatement();
            
			//5. 쿼리문을 전송하여 실행하고 실행결과를 받아와 저장
			rset = stmt.executeQuery(query);
            
			while(rset.next()) { //rest.next는 ture 혹은 false의 값을 반환하는 함수 
            // 쿼리의 모든 내용을 하나씩 조히하는 함수로 값이 존재할때는 true 없을때는 false를 반환
				//커서가 가르키고있는 row의 member_no 컬럼의 데이터를 가져와 정수로 리턴
				int memberNo = rset.getInt("member_no");
				//커서가 가르키고있는 row의 member_id 컬럼의 데이터를 가져와 문자열로 리턴
				String memberId = rset.getString("member_id");
                
				String memberName = rset.getString("member_name");
                
				char gender = rset.getString("gender").charAt(0);
                
				Date enrollDate = rset.getDate("enroll_date");
                
				// 커서를 통해서 1개 row의 모든데이터를 추출한 후 Member타입으로 묶어줌
				Member m = new Member(memberNo, memberId, memberName, gender, enrollDate);
                
				// 전체회원정보를 저장할 리스트에 1명정보를 추가
				list.add(m);
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				//6. 사용한 자원 반환
				rset.close();
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return list;
		
	}//selectAllMember end

설명을 적으라고 했는데 위에 주석으로 설명을 다 해놔버렸다... 뭐 쓸게없네.
위의 while문은 값이 없어서 반복문이 더이상 반복하지 않을때까지 계속 값을 ArratList에 넣어준다.

다음은 cotroller 패키지의 회원 1명 출력 매소드이다.

//아이디를 입력받아서 해당하는 회원의 정보를 조회하는 메소드
	public void selectOneMember() {
		System.out.print("아이디 입력 : ");
		String memberId = sc.next();
		Member m = dao.selectOneMember(memberId);
		if(m==null) { // 조회를 실패한경우
			System.out.println("정보를 조회할 수 없습니다.");
		}else {		//조회가 된 경우
			System.out.println("번호 : "+m.getMemberNO());
			System.out.println("아이디 : "+m.getMemberId());
			System.out.println("이름 : "+m.getMemberName());
			System.out.println("성별 : "+m.getGender());
			System.out.println("가입일 : "+m.getEnrollDate());			
		}
	} //selectOneMember end

그리고 dao패키지의 메소드이다.

public Member selectOneMember(String memberId) {
		// 1. 필요한변수 선언
		Connection conn = null;
		Statement stmt = null;
		ResultSet rset = null;
		
		Member m = null;
		String query = "select * from member where member_id='"+memberId+"'";
		
		try {
			//2. 사용할 DBMS드리이버 등록
			Class.forName("oracle.jdbc.driver.OracleDriver");// oracle.jdbc.driver.OracleDriver
            
			//3. 등록된 클래스로 연결 생성
			conn = DriverManager.getConnection 
					("jdbc:oracle:thin:@127.0.0.1:1521:xe","jdbc","1234");
                    
			//4. 쿼리문을 수행하고 결과를 받아올 Statement객체 생성
			stmt = conn.createStatement();
            
			//5. 쿼리문 수행 후 결과를 받아서 저장
			rset = stmt.executeQuery(query);
			
			if(rset.next()) {
				m = new Member();
				m.setMemberNO(rset.getInt("member_no"));
				m.setMemberId(rset.getString("member_id"));
                m.setMemberName(rset.getString("member_name"));
                m.setGender(rset.getString("gender").charAt(0));
                m.setEnrollDate(rset.getDate("enroll_date"));		
			}
			
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			try {
				rset.close();
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return m;
	}// selectOneMember end
}// class end

나중에 더 수정하러 오겠다. 지금은 상황이 아니다...

0개의 댓글