DB 연동

create table member_test(
    id varchar2(20) primary key,
    pwd varchar2(20),
    name varchar2(20),
    age number
);

insert into member_test values ('aaa', 'aaa', '홍길동', 20);
insert into member_test values ('bbb', 'bbb', '김개똥', 30);
insert into member_test values ('ccc', 'ccc', '고길똥', 40);
commit;

sqldeveloper 에서 연동용 member_test 테이블 하나 미리 생성해둠

 

프로젝트 생성

 

package ex01;

public class MemberDTO {
	// DB 의 컬럼과 동일한 자료형으로 DTO 생성
	private String id, pwd, name;
	private int age;
	
	// setter/getter 추가
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

DTO 에는 DB 의 컬럼 자료와 같은 자료형, 컬럼 명으로 변수를 생성

 

 

DB 다운로드 경로에 jdbc 폴더 하위에 ojdbc8.jar 라이브러리를 프로젝트에 추가해줘야 한다

ojdbc 라이브러리 추가 방법

 

 

ojdbc8 추가 후 module-info.java 파일에 sql 기능을 추가로 명시해줘야 작동한다

 

 

 

DB 연동 순서

프로젝트 라이브러리에 jdbc 를 추가 (위 동영상 참고) > module-info 에 라이브러리 추가 문구 작성 > 오라클 명령어를 사용할 수 있게 드라이버를 연동 ( Class.forName("oracle.jdbc.driver.OracleDriver") > Connection 객체를 통해 DB 연결 > PreparedStatement 객체를 통해 명령어를 DB 에 전송 > ResultSet 객체를 통해 명령어 수행 결과를 저장하여 출력

                             

package ex01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

class DB_con{
	// 연결을 시켜주는 Connetion 객체 ( 연결된 정보를 가지고 있음 )
	private Connection con;
	// 명령어를 전송하는 역할을 하는 PreparedStatement 객체
	private PreparedStatement ps;
	// 명령어 수행 결과 데이터를 저장하는 ResultSet 객체
	private ResultSet rs;
	
	public DB_con() {
		try {
			// jdbc 라이브러리 등록이 완료되었다면 아래 코드를 통해 오라클 드라이버의 기능을 사용할 수 있다
			Class.forName("oracle.jdbc.driver.OracleDriver");
			System.out.println("오라클 기능 사용가능(드라이버 로드)");
			
			// 18 버전 이전 : xe, 19 버전 이상 : orcl
			String url = "jdbc:oracle:thin:@localhost:1521:orcl"; // 오라클 DB 정보 ( 아이피:포트번호:버전 )
			String id = "c##youngho3358"; // DB 아이디
			String pwd = "1234"; // DB 비밀번호
			
			// 예외처리가 필요하므로 아래 catch 에서 exception 하나로 예외를 모두 처리
			// con 은 연결만 담당
			con = DriverManager.getConnection(url, id, pwd);
			System.out.println("db 연결 성공 : " + con);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public ArrayList<MemberDTO> select() {
		// 명령어를 문자열 형태로 담아서 사용
		String sql = "select * from member_test";
		// DTO 객체를 ArrayList 형태로 저장 ( 사용자들을 배열 형태로 저장 )
		ArrayList<MemberDTO> arr = new ArrayList<>();
		try {
			// ps 는 명령어를 전달하는 객체 ( 연결된 정보를 토대로 명령어를 전달 )
			ps = con.prepareStatement(sql);
			
			// ps 로 명령어를 전송하여 출력된 내용을 ResultSet 객체로 저장
			rs = ps.executeQuery();
			// System.out.println(rs.next());
			
			// 각 데이터를 자료형에 맞게끔 저장
			// rs 는 iterator 와 같은 방법으로 작동
			// ResultSet 의 메소드 getString() 의 괄호 안의 값은
			// 출력하고자 하는 컬럼의 이름이 들어가야 한다.
			while(rs.next()) {
				// DTO 에 출력되는 값들을 저장
				MemberDTO dto = new MemberDTO();
				dto.setId(rs.getString("id"));
				dto.setPwd(rs.getString("pwd"));
				dto.setName(rs.getString("name"));
				dto.setAge(rs.getInt("age"));
				
				// ArrayList 로 DTO 정보(DB로 받아온 정보)들을 배열로 저장
				arr.add(dto);
				
				/*
				System.out.println(rs.getString("id"));
				System.out.println(rs.getString("pwd"));
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("age"));
				System.out.println("-------------------------");
				*/
			}
			
			/*
			System.out.println(rs.next());
			System.out.println(rs.getString("id"));
			System.out.println(rs.getString("pwd"));
			System.out.println(rs.getString("name"));
			System.out.println(rs.getInt("age"));
			
			System.out.println(rs.next());
			System.out.println(rs.getString("id"));
			System.out.println(rs.getString("pwd"));
			System.out.println(rs.getString("name"));
			System.out.println(rs.getInt("age"));
			
			System.out.println(rs.next());
			*/
		} catch (Exception e) {
			e.printStackTrace();
		}
		return arr;
	}
	
	// 유저가 입력한 userId 를 전달받아 검색
	public MemberDTO selectOne(String userId) {
		// userId 값으로 검색하는 부분을 쿼리문으로 작성할때 문자열을 작음따옴표로 감싸줘야 함!!!!!!!
		String sql = "select * from member_test where id='" + userId + "'";
//		System.out.println(sql);
		
		MemberDTO dto = null;
		try {
			// 쿼리문을 DB로 전송
			ps = con.prepareStatement(sql);
			// 쿼리문이 작동된 결과 값을 저장
			rs = ps.executeQuery();
			
			// 검색된 결과 값이 있으면 DTO 객체에 해당 내용을 저장
			// 만약 검색될 결과 값이 없으면 DTO 객체는 null 값을 가진다
			if(rs.next()) {
				dto = new MemberDTO();
				dto.setId(rs.getString("id"));
				dto.setPwd(rs.getString("pwd"));
				dto.setName(rs.getString("name"));
				dto.setAge(rs.getInt("age"));
				/*
				System.out.println(rs.getString("id"));
				System.out.println(rs.getString("pwd"));
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("age"));
				*/
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return dto;
	}
	
	public int delete(String delId) {
		// ? 자리에 나중에 값을 채워넣겠다는 뜻
		String sql = "delete from member_test where id=?";
		int result = 0;
		try {
			ps = con.prepareStatement(sql);
			
			// 1 번째 물음표에 sql 을 대입한다는 뜻
			ps.setString(1, delId);
			
			// 쿼리문 동작 후 반환 값이 ResultSet 형태로 받을 필요가 없으니 executeUpdate() 메소드 사용하여
			// 리턴 값인 int 변수로 전달 받는다.
			// 쿼리문을 실행 시 정상 작동한다면 = 1 을 리턴
			// 쿼리문을 실행 시 오류가 발생한다면 = 0 을 리턴
			result = ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public int insert(MemberDTO dto) {
		String sql = "insert into member_test values(?,?,?,?)";
		int result = 0;
		try {
			ps = con.prepareStatement(sql);
			// 첫번째 물음표에 dto.getId 값 입력
			ps.setString(1, dto.getId());
			// 두번째 물음표에 dto.getPwd 값 입력
			ps.setString(2, dto.getPwd());
			// 세번째 물음표에 dto.getName 값 입력
			ps.setString(3, dto.getName());
			// 네번째 물음표에 dto.getAge 값 입력
			ps.setInt(4, dto.getAge());
			
			// insert 쿼리문을 사용할때 ps.executeUpdate(); 의 결과 값은
			// 성공 : 1, 실패 시 오류 문구가 출력된다 그래서 catch 로 넘어가게 되므로
			// 아이디 생성 실패 시 result 값은 최초 초기화 값인 0 이 리턴된다.
			result = ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
}

public class MainClass {
public static void main(String[] args) {
	DB_con db = new DB_con();
	
	Scanner input = new Scanner(System.in);
	int num;
	while(true) {
		System.out.println("1. 모든 목록보기");
		System.out.println("2. 특정 사용자 보기");
		System.out.println("3. 데이터 추가");
		System.out.println("4. 데이터 삭제");
		System.out.print(">>> : ");
		num = input.nextInt();
		switch(num) {
		case 1: 
			// ArrayList 로 담아온 정보를 반복문을 통해 출력
			ArrayList<MemberDTO> arr = db.select();
			System.out.println("--main--");
			for(MemberDTO dto : arr) {
				System.out.println("id : " + dto.getId());
				System.out.println("pwd : " + dto.getPwd());
				System.out.println("name : " + dto.getName());
				System.out.println("age : " + dto.getAge());
				System.out.println("-------------------");
			}
			break;
		case 2: 
			System.out.print("검색 id 입력 : ");
			String userId = input.next();
			// 입력받은 userId 값을 db 클래스의 selectOne 메소드로 넘겨줌
			// 메소드에서 실행되어 받아온 값을 DTO 형식으로 반환받아서 변수에 저장
			// id 가 존재한다면 dto 에 값이 정상적으로 들어갔을 것이며, 만약
			// id 가 존재하지 않는다면 dto 는 객체 생성 초기 값인 null 이 설정되어 있을 것이다.
			MemberDTO dto = db.selectOne(userId);
			if(dto == null) {
				// 만약 사용자가 존재하지 않아 dto 값이 null 로 반환되었다면
				System.out.println("존재하지 않는 id입니다!!!");
			}else {
				// 사용자가 존재해 dto 값이 쿼리문 결과 값으로 저장되었다면
				System.out.println("---- 검색 결과 ----");
				System.out.println("id : " + dto.getId());
				System.out.println("pwd : " + dto.getPwd());
				System.out.println("name : " + dto.getName());
				System.out.println("age : " + dto.getAge());
			}
			
			break;
		case 3: 
			MemberDTO d = new MemberDTO();
			
			// id 가 동일한 데이터가 db 에 존재하는지 확인
			while(true) {
				System.out.print("가입할 id 입력 : ");
				d.setId(input.next());
				MemberDTO dd = db.selectOne(d.getId());
				if (dd==null) {
					break;
				}
				System.out.println("존재하는 id... 다시 입력...");
			}
			
			System.out.print("가입할 pwd 입력 : ");
			d.setPwd(input.next());
			System.out.print("가입할 name 입력 : ");
			d.setName(input.next());
			System.out.print("가입할 age 입력 : ");
			d.setAge(input.nextInt());
			
			int res = db.insert(d);
			if(res == 1) {
				System.out.println("회원가입 성공!!!!");
			}else {
				System.out.println("존재하는 id는 안됨!!!");
			}
			break;
		case 4: 
			System.out.print("삭제 id 입력 : ");
			String delId = input.next();
			int re = db.delete(delId);
			if(re==1) {
				// 아이디가 존재해 쿼리문이 정상적으로 작동했다면...
				System.out.println("삭제 성공!!!");
			}else {
				// 아이디가 존재하지 않아 쿼리문이 정상적으로 작동하지 않았다면...
				System.out.println("존재하지 않는 아이디... 삭제 불가!!!");
			}
			break;
		}
	}
}
}
728x90

 

 

 

 

trunc, upper, lower

upper(정렬할 컬럼) : 대문자 정렬

lower(정렬할 컬럼) : 소문자 정렬

trunc(출력할 컬럼, 출력할 소수점 자릿 수) : 표현할 값을 표현할 자릿 수 까지만 출력한다

 

 

 

 

 

 

 

 

 

 

실습 예제

create table test_company(
  name varchar2(20),
  연봉 varchar2(20),
  class varchar2(20)
);
insert into test_company values('hong gil dong_M','3600','Manager');
insert into test_company values('kim gea ddong_M','2555','ManaGer');
insert into test_company values('Go gil dong_M','2800','ManaGER');
insert into test_company values('hong gil dong_E','3111','EmpLoyee');
insert into test_company values('kim gea ddong_E','2600','EmpLoYee');
insert into test_company values('Go gil dong_E','2950','employee');

위 코드 선 실행

실습 예제

 

 

예제 풀이

select * from test_company;
select * from test_company where upper(class)='MANAGER';
select * from test_company where lower(class)='employee' and 연봉 >= 2800;
select initcap(name), trunc(연봉/12,0) from test_company;

 

 

 

 

 

 

 

 

 

 

sum , avg , max , min , count , group by , having

create table test_class(class varchar2(10), score number);
Insert into test_class values('A반',11);
insert into test_class values('A반',12);
insert into test_class values('A반',13);
insert into test_class values('B반',21);
insert into test_class values('B반',22);
insert into test_class values('B반',23);
insert into test_class values('1',31);
insert into test_class values('1',32);
insert into test_class values('1',33);
insert into test_class values('',40);

위 코드 선 실행

 

select sum(score) from test_class; -- sum(컬럼) 컬럼의 총 합을 구함
select avg(score) from test_class; -- avg(컬럼) 컬럼의 총 평균을 구함
select max(score), min(score) from test_class; -- max(컬럼), min(컬럼) 컴럼의 최소값 최대 값 출력
select count(class) from test_class; -- 전체 갯수를 구하는데 값이 없는 곳은 갯수로 치지 않는다
select count(*) from test_class; -- 전체 갯수를 출력하는데 값이 없는 곳까지 모두 갯수로 쳐서 출력한다

select class, sum(score) from test_class group by class; -- group by (묶고자하는 컬럼) : 컬럼값이 동일한 것들로 정렬하여 묶어준다
select class, sum(score) from test_class group by class having sum(score)>60;
-- 그룹별로 묶여서 출력된 값 중 score의 합이 60 이상인 것들만 출력!!!
-- group by 를 사용하면 where 절은 사용이 불가능하여 having 절을 사용해야 한다!

sum(컬럼) : 컬럼의 총 합을 구함

avg(컬럼) : 컬럼의 총 평균을 구함

max(컬럼) : 컬럼의 최댓값을 출력

min(컬럼) : 컬럼의 최솟값을 출력

count(컬럼) : 컬럼의 데이터 갯수를 출력 ( 데이터가 비어있으면 갯수에 포함되지 않는다 )

count(*) : 전체 갯수를 출력하는데 값이 없는 곳까지 모두 갯수로 쳐서 출력한다

group by (묶고자하는 컬럼) : 컬럼의 데이터가 동일한 것들을 묶어서 출력한다

having (조건문) : group by 를 사용하면 where 문을 사용할 수 없으므로 조건을 추가할때 having 을 사용한다

 

실습 예제

 

실습 풀이

select class, count(class) from test_class group by class;
select class, avg(score) from test_class group by class order by avg(score) desc;
select class, min(score), max(score) from test_class group by class;

 

 

 

 

 

 

 

 

 

 

별칭, inner join

create table test_name(id varchar2(20), class varchar2(20));
Insert into test_name values('홍길동','A반');
insert into test_name values('김개똥','B반');
insert into test_name values('고길동','C반');

create table test_lesson(id varchar2(20), lesson varchar2(20), score number);
insert into test_lesson values('홍길동','python',80);
insert into test_lesson values('홍길동','java',90);
insert into test_lesson values('홍길동','c언어',70);
insert into test_lesson values('김개똥','server2012',70);
insert into test_lesson values('김개똥','linux',90);
insert into test_lesson values('고길동','jsp',100);

위 코드 선 실행

 

select * from test_name;
select * from test_lesson;

select * from test_name, test_lesson; -- id 가 중복되어서 출력됨
select N.*, L.lesson, L.score from test_name N, test_lesson L; -- 별칭을 부여하여 사용
-- N.* : test_name 을 N 으로 별칭하였으므로 N.* 은 test_name 의 모든 칼럼의 값
-- L.lesson : test_lesson 을 L 로 별칭하였으므로 L.lesson 은 test_lesson 의 lesson 칼럼의 값
-- L.score : test_lesson 을 L 로 별칭하였으므로 L.lesson 은 test_lesson 의 score 칼럼의 값

select N.*, L.lesson, L.score from test_name N, test_lesson L
                                    where N.id = L.id; -- L과 N의 ID 값이 같은 값들을 출력
                                    
select * from test_name N inner join test_lesson L on N.ID=L.id;
select N.*, L.lesson from test_name N inner join test_lesson L on N.ID=L.id;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

DB 툴

( 이 툴 이외에도 무료 툴이 많으니 DB 를 생성할때 툴을 이용하면 된다 )

 

AQueryTool

AQueryTool은 웹 기반 ERD 툴 + SQL 자동 생성 프로그램입니다.

aquerytool.com

 

 

 

 

 

실습 예제

( 클릭 시 확대 )

 

 

실습 풀이 1

DB 생성 tool 을 사용하여 DB 베이스 생성
각 DB 에 대한 생성 코드를 가져올 수 있다

CREATE TABLE memeber
(
    m_id      VARCHAR2(20)    NOT NULL, 
    m_pwd     VARCHAR2(20)    NULL, 
    m_name    VARCHAR2(20)    NULL, 
    m_addr    VARCHAR2(20)    NULL, 
     PRIMARY KEY (m_id)
);

-- goods 테이블 생성
CREATE TABLE goods
(
    g_num          INT             NOT NULL, 
    g_id           VARCHAR2(20)    NULL, 
    g_name         VARCHAR2(20)    NULL, 
    g_price        INT             NULL, 
    g_count        INT             NULL, 
    g_price_sum    INT             NULL, 
    g_date         DATE            NULL, 
     PRIMARY KEY (g_num)
);

-- g_num 컬럼에 Auto Increment 설정 ( 자동으로 수가 올라가면서 값이 저장 )
CREATE SEQUENCE goods_SEQ
START WITH 1
INCREMENT BY 1;

-- m_id 와 g_id 를 Foreign Key 로 서로 값을 연동 ( Foreign key 를 적용하면 저 둘의 값은 무조건 동일한 값이 존재해야 한다 )
ALTER TABLE goods
    ADD CONSTRAINT FK_goods_g_id_memeber_m_id FOREIGN KEY (g_id)
        REFERENCES memeber (m_id) ;

tool 에서 가져온 코드로 테이블을 생성

 

 

실습 풀이 2

-- 데이터 추가
insert into member(m_id, m_pwd, m_name, m_addr)
            values ('aaa', 'aaa', '홍길동', '산골짜기');
insert into member(m_id, m_pwd, m_name, m_addr)
            values ('bbb', 'bbb', '김개똥', '개똥별');
insert into member(m_id, m_pwd, m_name, m_addr)
            values ('ccc', 'ccc', '고길동', '마포구');
insert into member(m_id, m_pwd, m_name, m_addr)
            values ('ddd', 'ddd', '김말이', '분식집');

insert into goods values (1, 'aaa', '운동화', 75000, 2, 150000, sysdate);
insert into goods values (goods_seq.nextval, 'aaa', '티셔츠', 15000, 5, 75000, sysdate);
insert into goods values ((select max(g_num) from goods)+1, 'bbb', '가방', 450000, 1, 450000, sysdate);
insert into goods values ((select max(g_num) from goods)+1, 'bbb', '책', 35000, 2, 70000, sysdate);

select * from member;
select * from goods;

 

 

실습 풀이 3

-- inner join 을 사용하여 출력 ( id 가 중복됨을 기준으로 출력 )
select m.*, g.* from member m inner join goods g on m_id=g_id;
-- inner join 을 사용하여 출력 ( m_id, m_name, g_name, g_price_sum 컬럼만 출력 )
select m.m_id, m.m_name, g.g_name, g.g_price_sum from member m inner join goods g on m_id=g_id;
-- sum 함수를 이용하여 아이디 별 총 금액을 출력하시오
select m.m_id, m.m_name, m.m_addr, sum(g.g_price_sum) from member m inner join goods g on m.m_id = g.g_id group by m.m_id, m.m_name, m.m_addr;

inner join 사용법, group by 사용법 잘 파악하기!

728x90

 

 

 

 

Oracle DB 설치, sqldeveloper 설치

기존 PC 에 오라클 버전이 설치되어 있다면 버전을 확인한 뒤 구선생님께 "오라클 19c 완전 삭제" 와 같은 방식으로 검색하여 프로그램 삭제 뿐만이 아니라 완벽하게 설치나 설정을 날려준 뒤 시작한다.

 

 

 

 

 

DB, sqldeveloper 설치

 

15일차_ [DB] DB 다운로드

오라클 DB 다운로드 Oracle Database 19c Download for Microsoft Windows x64 (64-bit) Oracle Database 19c Grid Infrastructure (19.3) for Microsoft Windows x64 (64-bit) Contains the Grid Infrastructure Software including Oracle Clusterware, Automated St

youngho3358.tistory.com

 

 

 

 

 

Oracle DB 설치

 

1. C드라이브에 app 폴더 생성

app 폴더

 

 

2. 다운로드 받은 오라클 DB 를 app 폴더로 이동

폴더 이동

 

 

3. 압출 풀기

압축 풀기

 

 

4. 폴더 안의 setup.exe 클릭하여 설치

setup.exe 실행

 

 

5. 다음

 

 

6. 다음

 

 

7. 다음

 

 

8. 비밀번호 설정

오라클 설치 위치를 C:\app\oracle 로 지정한 뒤 비밀번호 설정

 

 

9. 예

 

 

10. 설치

 

 

11. 닫기

 

 

 

 

 

 

 

 

 

 

sqldeveloper 설치 및 DB 생성

 

1. sqldeveloper 압축 해제

 

 

2. sqldeveloper.exe 실행

 

 

3. 아니오 클릭

 

 

4. + 버튼 클릭

 

 

5. DB 의 이름, 사용자 이름(ID), 비밀번호 입력, ip정보, 포트 번호, DB 버전이 19 이상이라면 SID 값을 orcl 로 변경 후 저장 > 접속 클릭

최초 생성 system 은 모든 권한을 가진 사용자 (관리자) 로 생성됨 > 즉, 일반 계정을 생성해야 함

 

 

6. 방금 입력한 아이디 / 비밀번호 입력

 

 

7. 명령어 입력창 출력, 생성된 핀테크 DB 는 default 생성 DB 이다.

 

 

8. 계정 생성 ( c##youngho3358 / 1234 )

유저 생성 완료

코드 실행 : Ctrl + Enter

 

 

9. 방금 생성한 계정으로 DB 생성 시도 ( 테스트 버튼 클릭 )

계정을 생성되었지만 DB 접근 권한이 없기 때문에 오류 발생

 

 

10. dba(database admin) 권한 추가

권한 부여

 

 

11. 다시 DB 생성 시도 ( 테스트 버튼 클릭 ) 후 접속 클릭하여 DB 생성

 

 

12. DB 생성 완료

 

 

13. 테이블 생성 ( 테이블 명 : person )

create table person(
    num number, -- 숫자 저장 자료형
    name VARCHAR2(10), -- 문자 저장 자료형(byte)
    birth VARCHAR2(10),
    tel VARCHAR2(20),
    PRIMARY key( num ) 
    -- num 이라는 값을 기본 키로 설정
    -- num 값의 중복을 허용하지 않음을 의미
    -- null 값을 등록할 수 없고 값이 무조건 채워져 있어야 한다
);

create table <테이블명> ( 테이블 값 );

 

 

14. 생성된 테이블 확인

 

 

15. 테이블 확인 ( desc )

desc person;

person 테이블 확인

테이블 정보 출력

 

 

16. 테이블 하나 더 생성해보기

create table person111(
    num number, -- 숫자 저장 자료형
    name VARCHAR2(10), -- 문자 저장 자료형(byte)
    birth VARCHAR2(10) not null, -- null 값을 허용하지 않음
    tel VARCHAR2(20),
    PRIMARY key( name ) 
    -- num 이라는 값을 기본 키로 설정
    -- num 값의 중복을 허용하지 않음을 의미
    -- null 값을 등록할 수 없고 값이 무조건 채워져 있어야 한다
);

desc person111;

데이터 출력

 

 

17. person 테이블에 데이터 추가

insert into person values(1000,'홍길동','20230227',010-1111-2222);

데이터 추가된 것 확인

 

 

18. 테이블에 중복된 num 값으로 데이터 추가 시도

아까 테이블 생성할 때 num 값을 primary 키 값으로 중복을 허용하지 않았으므로 오류 발생

 

 

19. num 값을 변경한 뒤 정상적으로 데이터 추가 완료

 

 

20. 데이터를 추가하는 다른 방법

insert into person(num, name, birth, tel) values(1002,'성춘향','20191122',010-2222-3333);

각각의 추가될 컬럼 값을 순서대로 지정해 준 뒤 값을 적어서 데이터를 추가할 수도 있음

추가 성공

 

 

21. 데이터를 가지고 와서 출력

select * from person; -- person 테이블에 존재하는 모든 데이터를 출력
select num, name from person; -- person 테이블에 존재하는 num 과 name 의 데이터를 출력
select * from person where num = 1000; -- person 테이블로 부터 num 이 1000 과 같은 데이터의 모든 값을 출력
select * from person where name = '김기동'; -- person 테이블로 부터 name 이 김기동 과 같은 데이터의 모든 값을 출력

 

 

22. 현재 존재하는 테이블을 출력

select * from tab;

 

 

23. 테이블 삭제

delete from person; -- person 테이블 삭제
select * from person; -- 테이블이 삭제되어 출력되는 내용이 없음

 

 

24. 테이블의 데이터 삭제 및 변경

insert into person values(1000,'홍길동','20230227',01011112222);
insert into person values(1001,'김기동','20230222',01011113333);
insert into person(num, name, birth, tel) values(1002,'성춘향','20191122',01022223333);
-- 다시 삭제한 데이터 추가

delete from person where tel='01011113333'; -- person 테이블에서 전화번호가 01011113333 인 행 삭제
update person set name='김길이'; -- person 테이블의 모든 name 을 김길이 로 변경
update person set name='홍길동', birth='111' where num=1002; -- person 테이블의 num 이 1002 인 행의 이름을 홍길동, 생일을 111 로 변경

코드 실행 결과

 

 

25. developer 에서 작업할때는 모든 내용은 commit 이전에는 실제 DB 에 적용되지 않는다.

( 임시 저장소에서만 적용된다, 테이블을 생성하는 경우는 바로 적용된다 )

★ java 에서 작업할때는 자동으로 commit 이 진행된다 ★

commit; -- 커밋

delete from person; -- person 테이블의 모든 내용 삭제
select * from person;

rollback;
select * from person; -- 이전 커밋된 시점으로 되돌린다 ( person 테이블의 데이터가 commit 시점으로 복구됨 )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

실습 예제

(pk) 는 primary key 를 의미

 

실습 풀이

create table STUDENT(
    id VARCHAR2(10),
    name varchar2(10),
    kor VARCHAR2(5),
    eng VARCHAR2(5),
    math VARCHAR2(5),
    primary key( id )
);

insert into student values ( '15012248', '개똥이', '80', '95', '98' );
insert into student values ( '18262266', '춘향이', '98', '96', '90' );
insert into student(id, name, kor, eng, math) values ( '22068272', '멍청이', '25', '46', '60' );

update student set kor='70', eng='80', math='92' where id='22068272';

commit;

delete from student;

rollback;

select * from student;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

26. 테이블 정보 변경 ( 컬럼 추가, 컬럼 자료형 변경, 컬럼 삭제, 컬럼 이름 변경, 테이블 삭제 )

create table test_table(num number); -- num 이라는 컬럼을 가진 테이블 생성
desc test_table; -- 테이블 정보 출력

alter table test_table add ( name varchar2(20) ); -- name 이라는 컬럼을 추가
desc test_table; -- 테이블 정보 출력

alter table test_table modify ( name number ); -- name 컬럼의 자료형을 number 로 변경
desc test_table; -- 테이블 정보 출력

alter table test_table drop column name; -- name 컬럼을 삭제
desc test_table; -- 테이블 정보 출력

alter table test_table rename column num to num_b; -- num 컬럼의 이름을 num_b 로 변경
desc test_table; -- 테이블 정보 출력

drop table test_table; -- test_table 이라는 table 삭제
desc test_table; -- 테이블 정보 출력

 

 

27. 연산

create table STUDENT(
    id VARCHAR2(10),
    name varchar2(10),
    kor VARCHAR2(5),
    eng VARCHAR2(5),
    math VARCHAR2(5),
    primary key( id )
);

insert into student values ( '15012248', '개똥이', '80', '95', '98' );
insert into student values ( '18262266', '춘향이', '98', '96', '90' );
insert into student(id, name, kor, eng, math) values ( '22068272', '멍청이', '25', '46', '60' );

select * from student where eng >= 90; -- 영어가 90 보다 크거나 같은 사용자를 출력
select * from student where kor != 100; -- 숫자가 문자 형태로 저장되었지만 숫자로 연산할 수 있다
select math from student where name='춘향이'; -- 90 출력
select math/2 from student where name='춘향이'; -- 45 출력
select math + 100 from student where name='춘향이'; -- 190 출력
select math * 100 from student where name='춘향이'; -- 9000 출력
select mod(math,3) from student where name='춘향이'; -- 3으로 나눈 나머지인 0 출력
select * from student where kor>=90 and math=90; -- and 연산도 사용가능, 춘향이 행 출력
select * from student where not kor>=90; -- 국어 점수가 90 미만인 사용자 출력

select * from student where kor>=90 and kor<=100; -- 국어가 90 이상 100 이하인 사용자 출력
select * from student where kor between 90 and 100; -- 국어가 90 이상 100 이하인 사용자 출력

and, or, not 

 

 

28. number 자료형 자릿 수 설정

create table test_number(
    num_ps number(5, 2), -- 총 5자리 중 소수점 2자리 ( 즉, 정수는 3자리 )
    num_p number(3), -- 정수 3자리
    num number
);
insert into test_number values (1.123456, 1.123456, 1.123456); -- 저장 가능한 범위까지 저장된다.
insert into test_number values (1234.123456, 1.123456, 1.123456); -- num_ps 에 저장 가능한 정수 범위를 넘어서 오류 발생
insert into test_number values (1.123456, 1234.123456, 1.123456); -- num_p 에 저장 가능한 정수 범위를 넘어서 오류 발생
select * from test_number; -- 1.12, 1, 1.123456 출력

 

 

 

29. 날짜 자료형 

create table test_date(my_date date); -- date 자료형 컬럼인 my_date 를 가진 test_date 테이블 생성
insert into test_date values(sysdate); -- sysdate : 현재 날짜를 얻어오는 것 ( 시, 분, 초 도 저장됨 )
insert into test_date values('2000/12/24'); -- 날짜 추가 형식 ( 년, 월, 일 만 저장됨 )

alter session set nls_date_format = 'YYYY/MM/DD HH:MI:SS'; -- 기존 형식은 년/월/일 로 출력되는데 시/분/초 까지 출력되게 저장
select * from test_date; -- 년/월/일 시/분/초 까지 출력됨

insert into test_date values ('2000/12/24 12:12:12'); -- 년, 월, 일, 시, 분, 초 까지 저장됨
select * from test_date where my_date < '2024/02/27'; -- 날짜로도 연산이 가능, 2024년 02월 27일 이전 데이터만 출력됨

 

 

30. char 자료형과 varchar 자료형의 차이

create table test_char(
    ch char(5),
    var varchar2(20)
); -- char 자료형과 varchar 자료형이 따로 존재한다

-- char 자료형은 고정 자료형
-- varchar 자료형은 가변 자료형

insert into test_char values('1', '1');
select lengthb(ch), lengthb(var) from test_char; -- char 자료형은 5바이트 크기 출력, varchar 자료형은 1바이트 크기 출력
-- 고정 자료형은 바이트의 크기가 고정
-- 가변 자료형은 최대 바이트 크기만 지정해놓으면 해당 크기 내에서 저장되는 자료형의 크기로 변환됨

 

 

31. 와일드 카드, 검색 필터 ( order by, desc, asc )

create table STUDENT(
    id VARCHAR2(10),
    name varchar2(10),
    kor VARCHAR2(5),
    eng VARCHAR2(5),
    math VARCHAR2(5),
    primary key( id )
);

insert into student values ( '15012248', '개똥이', '80', '95', '98' );
insert into student values ( '18262266', '춘향이', '98', '96', '90' );
insert into student(id, name, kor, eng, math) values ( '22068272', '멍청이', '25', '46', '60' );

select * from student;
insert into student values('4', '길고인', '10', '10', '10');
select * from student where name like '김%'; -- name 이 김으로 시작하는 모든 자료를 다 가져옴
select * from student where name like '%인'; -- name 이 인으로 끝나는 모든 자료를 다 가져옴
select * from student where name like '%이%'; -- name 에 이 라는 문자가 들어간 모든 자료를 다 가져옴

select * from student;
select * from student order by name desc; -- 이름을 기준으로 내림차순으로 데이터를 출력
select * from student order by name asc; -- 이름을 기준으로 오름차순으로 데이터를 출력

select * from student order by eng desc; -- 영어를 기준으로 내림차순으로 데이터를 출력

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

실습 예제

 

insert into employee values('설까치',1800000,'삼성','2017/10/24');
insert into employee values('로버트',1850000,'애플','2019/01/04');
insert into employee values('고도리',2200000,'엘지','2017/11/06');
insert into employee values('김개똥',2500000,'SK','2017/04/14');
insert into employee values('리우뚱',2410000,'샤오미','2018/01/09');
insert into employee values('강민',1900000,'삼성','2019/10/24');
insert into employee values('할리',1800000,'애플','2019/12/04');
insert into employee values('심심해',4630000,'엘지','2015/04/02');
insert into employee values('놀아줘',2770000,'SK','2017/01/24');
insert into employee values('왕만두',3650000,'샤오미','2016/08/04');
insert into employee values('머리빨',4210000,'삼성','2015/03/18');
insert into employee values('마리오',2720000,'애플','2017/01/04');
insert into employee values('최치우',4320000,'엘지','2015/06/07');
insert into employee values('안깔쌈',3490000,'SK','2015/09/07');
insert into employee values('끝짱',2200000,'샤오미','2017/05/04');
insert into employee values('막장',1920000,'삼성','2018/11/24');
insert into employee values('드라마',3420000,'애플','2016/07/29');
insert into employee values('개똥이',1800000,'엘지','2018/12/24');
insert into employee values('마포구',2230000,'SK','2018/01/05');
insert into employee values('소고기',1800000,'샤오미','2019/01/09');
insert into employee values('짜장면',2100000,'삼성','2017/10/24');
insert into employee values('소곱창',2200000,'애플','2017/11/04');
insert into employee values('참이슬',1950000,'엘지','2017/10/24');
insert into employee values('뤼우뚱',1800000,'SK','2018/10/24');
insert into employee values('위메프',1800000,'샤오미','2019/12/07');
insert into employee values('북경시',1880000,'삼성','2018/11/14');
insert into employee values('스미스',1970000,'애플','2019/06/04');
insert into employee values('핸드폰',7200000,'엘지','2010/01/27');
insert into employee values('빅스비',3570000,'SK','2015/02/17');
insert into employee values('노라줘',3200000,'샤오미','2015/11/24');
insert into employee values('사이다',2400000,'삼성','2017/09/26');
insert into employee values('김말이',7000000,'애플','2010/01/21');
insert into employee values('오도독',6230000,'엘지','2011/08/19');

insert into employee values('쌈지돈',3710000,'SK','2015/08/19');
insert into employee values('화장지',1770000,'샤오미','2019/04/28');
insert into employee values('소화기',1920000,'삼성','2019/10/07');
insert into employee values('박효신',2670000,'애플','2017/11/24');
insert into employee values('판빙빙',3120000,'엘지','2016/05/19');
insert into employee values('김재욱',4190000,'SK','2015/01/02');
insert into employee values('송혜교',4280000,'샤오미','2015/01/02');
insert into employee values('송중기',3700000,'삼성','2016/02/17');
insert into employee values('손홍민',2220000,'애플','2018/02/04');
insert into employee values('백종원',2760000,'엘지','2017/10/14');
insert into employee values('오창석',2620000,'SK','2017/09/04');
insert into employee values('스텔라',2500000,'샤오미','2017/11/20');
insert into employee values('멕스웰',1970000,'삼성','2017/10/30');
insert into employee values('조현',  2720000,'애플','2018/11/11');
insert into employee values('류현진',2600000,'엘지','2015/11/19');
insert into employee values('은지원',5670000,'SK','2017/10/16');
insert into employee values('전효성',3750000,'샤오미','2015/09/15');
insert into employee values('이채은',3400000,'삼성','2016/02/09');
insert into employee values('최고봉',8900000,'애플','2010/01/04');
insert into employee values('광화문',1860000,'엘지','2017/10/24');
insert into employee values('동대문',1790000,'SK','2017/10/24');
insert into employee values('서대문',2880000,'샤오미','2016/02/27');
insert into employee values('대통령',2320000,'삼성','2016/05/24');
insert into employee values('예지원',1780000,'애플','2019/01/09');
insert into employee values('정소민',2900000,'엘지','2016/10/22');
insert into employee values('워너원',3000000,'SK','2015/10/10');
insert into employee values('북한군',3200000,'샤오미','2015/11/11');
insert into employee values('남한군',2500000,'삼성','2016/12/19');
insert into employee values('짜투리',1850000,'애플','2018/04/03');
insert into employee values('이승기',1900000,'엘지','2018/01/01');
insert into employee values('기차길',1790000,'SK','2018/05/02');
insert into employee values('길거리',2700000,'샤오미','2016/07/20');

데이터 미리 등록하고 시작

 

 

예제 풀이1

create table employee(
    name  VARCHAR2(15),
    salary  number,
    job  varchar2(20),
    join_company  date
);

insert into employee values('홍길동', 2000000, '컴퓨터', '2222/12/24');
alter session set nls_date_format = 'YYYY/MM/DD';
select * from employee;

테이블 생성한 뒤 미리 집어 넣을 모든 데이터를 저장

 

 

예제 풀이 2

delete from employee; -- 홍길동 이름을 가진 데이터 삭제
select * from employee;

-- 이후 데이터 모두 복사 붙여넣기해서 저장 --

select * from employee where salary*12 > 100000000; -- 연봉이 1억이 넘는 사람 출력
select name, join_company from employee where join_company < '2014/12/31'; -- 2015년도 이전에 입사한 사람의 이름과 입사년도 출력
select * from employee where salary between 2800000 and 3000000; -- 월급이 280만원 ~ 300만원인 사람 출력

 

 

예제 풀이 3

select * from employee where join_company>= '2015/01/01' and salary*12 > 60000000; -- 입사년도가 2015년 이상이며 연봉이 6000만원 이상인 사람들을 출력
select * from employee where (job = '엘지' or job =  '삼성') and salary*12 > 50000000; -- 회사가 삼성이거나 엘지이며 연봉이 5000만원 이상인 사람들을 출력

 

 

예제 풀이 4

select * from employee where name like '%김%' and salary*12 >= 30000000 order by job asc, salary desc;
-- 회사는 오름 차순으로 정렬하고 연봉은 내림 차순으로 정렬하고 이름에 '김'이 들어가며 연봉은 3000만원 이상인 모든 내용을 출력하시오

 

 

 

 

 

 

 

 

 

 

실습 예제

 

insert into test_func values(3,'77');
insert into test_func values(4,'67.123');
insert into test_func values(5,'123.123');
insert into test_func values(6,'99');
insert into test_func values(7,'99.456');
insert into test_func values(8,'128');
insert into test_func values(9,'123.777');
insert into test_func values(10,'101.44');

select * from test_func where mod(id,2)=1;
select id, round(num/2,2) from test_func where mod(id,2)=0;
728x90

 

 

 

 

 

네트워크 프로그래밍

TCP, UDP 통신

 

네트워크 프로그래밍

 

 

소켓을 사용하여 server 와 client 구성하여 데이터 수, 발신

 

package tcp;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Ex01_server {
	public static void main(String[] args) throws Exception {
		// 서버소켓 클래스 객체 생성
		// 예외처리 필요, 12345 는 Port 번호
		ServerSocket server = new ServerSocket(12345);
		System.out.println("접속을 기다립니다!!!");
		
		// accept() - 클라이언트가 연결될때까지 기다리는 메소드
		// 즉, 클라이언트가 연결되어야 "클라이언트 연결되었습니다!!!" 문구가 실행됨
		// server.accept() 를 소켓 객체로 담아 접속 클라이언트의 정보를
		// sock 이라는 이름으로 저장한다
		Socket sock = server.accept();
		System.out.println("클라이언트 연결되었습니다!!!");
		
		// InputStream 이라는 객체 입력 클래스 객체를
		// 소켓을 통해 사용하겠다.
		InputStream is = sock.getInputStream();
		
		// 데이터 수신
		int readData = is.read();
		System.out.println("수신 데이터 : " + readData);
		
		is.close(); sock.close(); server.close();
	}
}

Server

 

package tcp;

import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex01_client {
	public static void main(String[] args) throws Exception {
		// 현재 학원 PC 아이피 : 192.168.42.118
		// Server socket 설정 포트번호 : 12345
		// 클라이언트는 소켓 클래스 객체로 서버에 연결 요청
		// 객체 생성 시 아이피 정보, 포트 정보가 들어감
		Socket sock = new Socket("192.168.42.118", 12345);
		System.out.println("클라이언트 실행!!!");
		
		// OutputStream ㅇ;라는 데이터 출력 클래스 객체를
		// sock 이라는 소켓을 통해 사용하겠다
		OutputStream os = sock.getOutputStream();
		
		Scanner input = new Scanner(System.in);
		System.out.print("수 입력 : ");
		int data = input.nextInt();
		
		// 데이터 전송
		os.write(data);
		os.close(); sock.close();
	}
}

Client

 

기본 스트림이 전송할 수 있는 값은 1 byte 단위이다.

1 byte = 0 ~ 255

 

만약 256 을 전송하였다면 0 으로 server 가 받으며, 257 을 전송하였다면 1 로 server 가 받는다.

그러므로 보조 스트림을 사용하여 문자열, 객체 등을 전송할 수 있게 해줘야 한다.

 

 

 

 

 

 

 

 

 

 

보조스트림을 사용하여 문자열을 수, 발신 하기

보조스트림 DataInput, DataOutput 클래스를 사용하여 문자열 수, 발신

 

package tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Ex02_server {
	public static void main(String[] args) throws Exception {
		// 서버 소켓 생성, 포트번호 10000
		ServerSocket server = new ServerSocket(10000);
		System.out.println("접속 대기....");
		
		// Socket 클래스로 클라이언트의 정보를 담아둠
		Socket sock = server.accept();
		
		// 현재 서버 접속자의 정보 출력
		System.out.println(sock.getInetAddress());
		
		InputStream in = sock.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		
		// 수신한 데이터(문자열) 저장
		String readData = dis.readUTF();
		
		System.out.println("수신 데이터 : " + readData);
		
		// sock 에는 이미 클라이언트에 대한 정보가 들어있으므로
		// sock 을 이용하여 클라이언트로 데이터를 전송할 수 있음
		OutputStream os = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);
		
		Scanner input = new Scanner(System.in);
		System.out.print("클라이언트로 전송할 데이터 입력 : ");
		String sendData = input.nextLine();
		dos.writeUTF(sendData);
		
		dis.close(); in.close();
		dos.close(); os.close();
		sock.close(); server.close();
	}
}

Server

 

package tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex02_client {
	public static void main(String[] args) throws Exception {
		// 로컬 루프백 주소인 127.0.0.1 로 지정, 포트 10000 으로 접속 시도
		Socket sock = new Socket("127.0.0.1", 10000);
		
		OutputStream out = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		Scanner input = new Scanner(System.in);
		System.out.print("전송할 문자열 입력 : ");
		String data = input.nextLine();
		
		dos.writeUTF(data);
		
		InputStream is = sock.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		String readData = dis.readUTF();
		
		System.out.println("수신 데이터 : " + readData);
		
		dos.close(); out.close();
		dis.close(); is.close();
		sock.close();
	}
}

Client

 

 

 

 

 

 

 

 

 

 

클라이언트 두 곳과 연결

클라이언트 두 곳과 연결, 우선 연결에 따라 연결 정보가 sock1, sock2 로 저장된다

 

package tcp;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Ex03_server {
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(12345);
		System.out.println("접속을 기다립니다...");
		
		// 접속 순서에 따라 sock01, sock02 로 클라이언트에 대한 정보를 저장한다
		Socket sock01 = server.accept();
		Socket sock02 = server.accept();
		System.out.println("접속 되었습니다.");
		
		// sock01 로부터 날아오는 데이터를 저장한다.
		// sock02 에서 날아온 데이터는 따로 저장되지 않는다...!!
		InputStream in = sock01.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		
		String readData = dis.readUTF();
		System.out.println("수신 데이터 : " + readData);
		
		dis.close(); in.close(); sock01.close(); sock02.close();
		server.close();
	}
}

Server

 

package tcp;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex03_client01 {
	public static void main(String[] args) throws Exception {
		Scanner input = new Scanner(System.in);
		Socket sock = new Socket("127.0.0.1", 12345);
		
		OutputStream out = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		System.out.print("송신 데이터 입력 : ");
		String data = input.nextLine();
		dos.writeUTF(data);
		
		dos.close(); out.close(); sock.close(); input.close();
	}
}

Client01

 

package tcp;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex03_client02 {
	public static void main(String[] args) throws Exception {
		Scanner input = new Scanner(System.in);
		Socket sock = new Socket("127.0.0.1", 12345);
		
		OutputStream out = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		System.out.print("송신 데이터 입력 : ");
		String data = input.nextLine();
		dos.writeUTF(data);
		
		dos.close(); out.close(); sock.close(); input.close();
	}
}

Client02

 

 

 

 

 

 

 

 

 

 

객체를 직렬화하여 전송하기

직렬화 - 객체를 byte 형식으로 변환

객체는 byte 형식으로 직렬화하여 보내지 않으면 오류가 발생하기 때문에 꼭 직렬화 를 하여 전송해야 한다

직렬화하여 객체를 전송!!!! 직렬화 필수

 

package tcp;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Ex04_server {
	public static void main(String[] args) throws Exception {
		ServerSocket server = new ServerSocket(12345);
		System.out.println("접속 대기");
		Socket sock = server.accept();
		System.out.println("접속 되었음");
		
		InputStream in = sock.getInputStream();
		ObjectInputStream ois = new ObjectInputStream(in);
		
		Ex04_DTO dto = (Ex04_DTO)ois.readObject();
		System.out.println("수신 name : " + dto.getName());
		System.out.println("수신 addr : " + dto.getAddr());
		
		ois.close(); in.close(); sock.close();
		server.close();
	}
}

Server

 

package tcp;

import java.io.Serializable;

public class Ex04_DTO implements Serializable{
					// Serializable 상속하여 꼭 직렬화 해주기!
	private String name, addr;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddr() {
		return addr;
	}
	public void setAddr(String addr) {
		this.addr = addr;
	}
}

DTO

 

package tcp;

import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex04_client {
	public static void main(String[] args) throws Exception {
		Socket sock = new Socket("127.0.0.1", 12345);
		
		Scanner sc = new Scanner(System.in);
		
		OutputStream out = sock.getOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(out);
		
		Ex04_DTO dto = new Ex04_DTO();
		System.out.print("이름 입력 : ");
		dto.setName(sc.next());
		System.out.print("주소 입력 : ");
		dto.setAddr(sc.next());
		
		oos.writeObject(dto);
		oos.close(); out.close(); sock.close();
	}
}

Client

 

 

 

 

 

 

 

 

 

 

쓰레드를 사용하여 다중 client 에게 데이터 전송받기

Thread 를 사용하지 않으면 클라이언트에게 응답을 받을때 하나씩 받거나 응답이 오지않으면 무한대기에 빠지기 때문에 쓰레드를 사용하여 다중의 데이터를 받아 처리한다

 

 

 

 

 

 

 

 

 

 

다자간 채팅 서버

다자간 채팅 서버 구현

 

기억할 것 : 소켓으로 클라이언트가 접속하면 서버는 ArrayList 를 사용하여 클라이언트의 Socket 정보를 배열로 저장한뒤 수신 받은 데이터를 변수로 다시 선언하여 OutputStream 을 사용하여 ArrayList 안에 담긴 Socket 정보로 다시 전송하는 형태

 

Server 의 Thread : 다중 클라이언트의 데이터를 전송받고 다시 연결된 클라이언트들에게 데이터를 전송하기 위해 사용

Client 의 Thread : 발신은 Thread 를 사용하지 않고 클라이언트에서 진행되며, Thread 를 사용하여 실시간으로 들어오는 데이터를 수신

 

package tcp;

import java.net.ServerSocket;
import java.net.Socket;

public class Ex06_server {
	public static void main(String[] args) throws Exception {
		
		ServerSocket server = new ServerSocket(12345);
		
		while(true) {
			System.out.println("접속을 기다립니다...");
			Socket s = server.accept();
			System.out.println(s.getInetAddress() + "님 접속");
			
			// 쓰레드 객체를 생성
			new Ex06_serverThread(s);
		}
	}
}

Server

 

package tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;

public class Ex06_serverThread extends Thread {
	// arr 변수를 static 으로 선언하여 모든 쓰레드가 공유하여 사용할 수
	// 있게끔 생성한다
	public static ArrayList<Socket> arr;
	static {
		arr = new ArrayList<>();
	}
	private Socket s;
	public Ex06_serverThread(Socket s) {
		// ArrayList 에 사용자들의 정보(소켓)를 저장
		arr.add(s);
		this.s = s;
		start(); // start 메소드 실행 시 run 메소드 자동 실행
	}
	@Override
	public void run() {
		try {
			// InputStream in = arr.get( arr.size()-1 ).getInputStream();
			
			// 현재 접속한 사용자로부터 데이터를 수신
			InputStream in = s.getInputStream();
			DataInputStream dis = new DataInputStream(in);
			while(true) {
				// 수신한 데이터를 변수에 저장
				// readUTF 메소드는 입력값이 들어올때까지 대기하다가 입력 값이
				// 들어오면 그때 메소드가 동작한다!!!!
				// 그러므로 빈 값을 클라이언트에게 무한으로 던지지 않는다
				String msg = dis.readUTF();
				for(Socket ss : arr) {
					// 배열로 저장된 현재 연결된 클라이언트들에게 수신 데이터를
					// 다시 전송
					OutputStream out = ss.getOutputStream();
					DataOutputStream dos = new DataOutputStream(out);
					dos.writeUTF(msg);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Server Thread

 

package tcp;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex06_client01 {
	public static void main(String[] args) throws Exception {
		// 소켓 생성
		Socket sock = new Socket("127.0.0.1", 12345);
		OutputStream out = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		Scanner sc = new Scanner(System.in);
		String msg = null;
		
		// 수신되는 데이터는 쓰레드 객체를 생성하여 수신
		Ex06_clientThread rcv = new Ex06_clientThread(sock);
		
		while(true) {
			// 클라이언트에서 전송하는 데이터는 while 문으로 계속 입력받음
			System.out.print("전송 데이터 입력 : ");
			msg = sc.nextLine();
			dos.writeUTF(msg);
		}
	}
}

Client01

 

package tcp;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Ex06_client02 {
	public static void main(String[] args) throws Exception {
		// 소켓 생성
		Socket sock = new Socket("127.0.0.1", 12345);
		OutputStream out = sock.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		Scanner sc = new Scanner(System.in);
		String msg = null;
		
		// 수신되는 데이터는 쓰레드 객체를 생성하여 수신
		Ex06_clientThread rcv = new Ex06_clientThread(sock);
		
		while(true) {
			// 클라이언트에서 전송하는 데이터는 while 문으로 계속 입력받음
			System.out.print("전송 데이터 입력 : ");
			msg = sc.nextLine();
			dos.writeUTF(msg);
		}
	}
}

Client02

 

package tcp;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.Socket;

public class Ex06_clientThread extends Thread {
	Socket sock;
	public Ex06_clientThread(Socket sock) {
		// 클라이언트가 객체 생성할때 들고온 Socket 정보를 sock 으로 저장
		// 서로 다른 클라이언트가 접근하면 클라이언트 1개 당
		// 쓰레드 객체가 1개씩 신규로 생성된다
		this.sock = sock;
		start(); // 쓰레드에서 start 메소드가 실행되면 run 메소드도 자동으로 실행된다
	}
	@Override
	public void run() {
		try {
			// Socket 으로 연결된 서버에서 전달 받는 정보를 쓰레드를 사용하여
			// 메세지를 발신하면서도 독립적으로 계속 수신받게끔 설정
			InputStream in = sock.getInputStream();
			DataInputStream dis = new DataInputStream(in);
			while(true) {
				String data = dis.readUTF();
				System.out.println("수신 데이터 : " + data);
			}
		}catch (Exception e) {
		}
	}
}

Client Thread

 

 

- 프로그램 작동 순서 -

Server 에서 서버 소켓 생성 후 클라이언트가 접속하는 것을 대기

 

> 클라이언트 1 이 서버 소켓에 접속

> 서버쓰레드가 공유하는 arr 배열에 클라이언트 1의 소켓 정보를 저장

> 서버 쓰레드 1 과 클라이언트 1 쓰레드가 동시에 생성 및 작동

 

> 클라이언트 2 가 서버 소켓에 접속

> 서버쓰레드가 공유하는 arr 배열에 클라이언트 2의 소켓 정보를 저장

> 서버 쓰레드 2 와 클라이언트 2 쓰레드가 동시에 생성 및 작동

 

> 클라이언트 1에서 데이터를 전송

> 서버 쓰레드 1 에서 전송받은 데이터를 arr 배열에 존재하는 사용자정보(Socket)에 모두 전송

> 클라이언트 쓰레드 1, 2 는 서버쓰레드 1 에서 전송받은 데이터를 출력

 

> 클라이언트 2에서 데이터를 전송

> 서버 쓰레드 2 에서 전송받은 데이터를 arr 배열에 존재하는 사용자정보(Socket)에 모두 전송

> 클라이언트 쓰레드 1, 2 는 서버쓰레드 2 에서 전송받은 데이터를 출력

728x90

 

맥북을 구매하여 사용하는 김에 개발에 사용하는 IDE를 이클립스에서 인텔리제이로 변경해보려 한다.

 

 

⌥ : option

⌘ : command

⇧ : Shift

^ : control

 

 

맥북 자주 사용하는 단축키

⌘ + 방향키 한줄 이동
⌥ + 방향키 음절 별로 이동
fn + ⌫ delete
fn + ← Home 키
fn + → End 키
⌘ + ↑ Page Up 키
⌘ +  Page Down 키
⌘ + tab 윈도우의 Alt + Tab
⌘ + C 복사
⌘ + V 붙여넣기
⌘ + Z 되돌리기
   
   
   
   
   
⌥, ⌘, ⇧, ⇪, ⎋, ^  

 

 

 

인텔리제이 단축키

^ + Space Bar 자동 완성 ( 패키지 목록 띄워줌 )
⌘ + n 생성자, getter / setter 생성
⌘ + / 한 줄 주석
⌘ + Shift + / 여러 줄 주석
⌘ + Shift + ↑↓ 선택 코드 줄 위, 아래로 이동
⌘ + d 한 줄 복사
⌘ + 한 줄 삭제
Shift + ⌘ + Enter 구문 완성 ( ; 를 닫아준다 )
   
   
   
728x90

 

 

 

 

 

미니 프로젝트

- DB 를 연동하지 않아서 코드를 실행할때마다 데이터가 초기화 되는 문제를 파일로 객체 정보를 저장하여 해결해보자...!!!

 

 

 

회원 정보를 파일로 저장하고 등록, 확인, 탈퇴할 수 있는 프로그램

package file.main;

import java.util.Scanner;

import file.service.ServiceMember;
import file.service.ServiceMemberImpl;

public class MainClass {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int num;
		ServiceMember member = new ServiceMemberImpl();
		
		while(true) {
			System.out.println("1. 회원가입");
			System.out.println("2. 검 색");
			System.out.println("3. 회원 목록 보기");
			System.out.println("4. 탈 퇴");
			System.out.println("5. 종 료");
			System.out.print(">>>> : ");
			num = sc.nextInt();
			
			switch(num) {
			case 1 : 
				member.register();
				break;
			case 2 : 
				member.search();
				break;
			case 3 : 
				member.list();
				break;
			case 4 : 
				member.delete();
				break;
			case 5 : 
				System.out.println("프로그램을 종료합니다.");
				break;
			default : 
				System.out.println("잘못 입력하셨습니다.");
				break;
			}
		}
	}
}

MainClass

 

package file.service;

public interface ServiceMember {
	public void register();
	public void list();
	public void delete();
	public void search();
}

ServiceMember

 

package file.service;

import java.util.Scanner;

import file.dao.MemberDAO;
import file.dto.MemberDTO;

public class ServiceMemberImpl implements ServiceMember {
	private MemberDAO dao;
	public ServiceMemberImpl() {
		dao = new MemberDAO();
	}
	
	@Override
	public void register() {
		MemberDTO dto = new MemberDTO();
		Scanner sc = new Scanner(System.in);
		System.out.print("아이디 입력 : ");
		dto.setId(sc.next());
		System.out.print("이름 입력 : ");
		dto.setName(sc.next());
		
		dao.register(dto);
	}
	
	public void list() {
		String[] listFile = dao.getList();
		if(listFile.length == 0) {
			System.out.println("저장된 목록이 없습니다!!!");
		}else {
			for(int i=0; i<listFile.length; i++) {
				System.out.println(i + ". " + listFile[i]);
			}
		}
	}
	
	public void delete() {
		Scanner sc = new Scanner(System.in);
		String id;
		System.out.print("삭제할 id 입력 : ");
		id = sc.next();
		dao.delete(id);
	}
	
	public void search() {
		Scanner sc = new Scanner(System.in);
		String id;
		System.out.print("검색할 id 입력 : ");
		id = sc.next();
		MemberDTO d = dao.search(id);
		if(d != null) {
			System.out.println("id : " + d.getId());
			System.out.println("name : " + d.getName());
		}
	}
}

ServiceMemberImpl

 

package file.dto;

import java.io.Serializable;

import lombok.Data;

@Data
public class MemberDTO implements Serializable{
					// serializble 상속 받아 직렬화
	private String id, name;
}

MemberDTO

 

package file.dao;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import file.dto.MemberDTO;

public class MemberDAO {
	// 객체가 저장될 path 설정
	private String path = "E:\\0.핀테크\\members\\";
	
	// 파일 입출력에 관련된 객체들을 선언
	private FileInputStream fis;
	private FileOutputStream fos;
	private BufferedInputStream bis;
	private BufferedOutputStream bos;
	private ObjectInputStream ois;
	private ObjectOutputStream oos;
	
	// 객체를 외부로 전송....
	public void register(MemberDTO dto) {
		//  String p = path + dto.getId() + ".txt";
		
		// 파일 클래스의 기능들을 사용하기 위해 String 자료형이 아닌
		// File 클래스를 사용
		File p = new File(path + dto.getId() + ".txt");
		
		// 동일한 이름의 회원 파일이 있는지 확인
		if(p.exists()) {
			System.out.println("이미 존재하는 회원입니다.");
		}else {
			try {
				fos = new FileOutputStream(p);
				bos = new BufferedOutputStream(fos);
				oos = new ObjectOutputStream(bos);
				oos.writeObject(dto);
				
				oos.close(); bos.close(); fos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("회원가입 성공!!!!!");
		}
	}
	
	public String[] getList() {
		File file = new File(path);
		return file.list();
	}
	
	public void delete(String id) {
		File file = new File(path + id + ".txt");
		if(file.exists()) {
			file.delete();
			System.out.println(id + " 가 삭제되었습니다.");
		}else {
			System.out.println("존재하지 않는 회원입니다.");
		}
	}
	
	public MemberDTO search(String id) {
		File file = new File(path + id + ".txt");
		MemberDTO dto = null;
		if(file.exists()) {
			try {
				fis = new FileInputStream(file);
				bis = new BufferedInputStream(fis);
				ois = new ObjectInputStream(bis);
				dto = (MemberDTO)ois.readObject();
				ois.close();
				bis.close();
				fis.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("찾는 회원이 없습니다.");
		}
		return dto;
	}
}

MemberDAO

728x90

 

 

 

 

 

직렬화 ( Serializable )

직렬화 ( Serializable ) - 객체를 byte 로 형변환해서 저장하는 것

객체를 DB 에 저장할 때 객체 자체로는 저장이 불가능하기 때문에 byte 로 형태를 변환하여 DB 에 저장한다.

 

 

전송하려는 객체를 직렬화 ( serializable ) 하여 ObjectOutpuStream 을 사용하여 외부로 전송

 

 

외부로 전송하여 byte 형태 문자로 test.txt 에 저장되어 있는 Ex09DTO 자료형의 자료를 역으로 읽어오는 과정

ObjectInputStream 사용하여 객체를 읽어옴

728x90

 

 

 

 

 

 

오라클 DB 다운로드

 

Oracle Database 19c Download for Microsoft Windows x64 (64-bit)

Oracle Database 19c Grid Infrastructure (19.3) for Microsoft Windows x64 (64-bit) Contains the Grid Infrastructure Software including Oracle Clusterware, Automated Storage Management (ASM), and ASM Cluster File System. Download and install prior to install

www.oracle.com

Oracle DB 19c 버전을 사용해볼 것임

 

 

product 하단의 Oracle Database 클릭

 

 

오라클 데이터베이스 19c 다운로드 클릭

 

 

개별 구성요소 다운로드 클릭

 

 

클릭하여 다운로드

 

 

 

DB 를 피씨에 다운로드 받으면 피씨가 DB 가 된다.

만약 집에서 DB 작업을 하고 회사에서 DB 작업을 이어서 진행하고 싶은 경우에 DB 회사에서 제공하는 클라우드를 사용해서 연동하면 된다.

 

 

 

 

 

 

 

 

 

 

SQL Developer 다운로드

 

SQL Developer

Oracle SQL Developer는 무료 개발 환경으로 전통적인 배포 및 클라우드 배포 모두에서 Oracle Database의 관리를 간소화해 줍니다. 또한 PL/SQL 애플리케이션, 쿼리 도구, DBA 콘솔, 보고서 인터페이스 등의

www.oracle.com

 

 

Windows 64-bit with JDK 11 included 다운로드 버튼 눌러서 다운로드

 

728x90

+ Recent posts