본문 바로가기

STUDY/국비과정

[JAVA 웹 개발 공부] 국비지원 43일차 - PreparedStatement, JOIN, 트랜잭션, MySQL 반복문, 조건문, Constraint

메소드에 예외 선언하기 - throws


예외를 메서드의  throws에 명시하는 것은 예외를 처리하는 것이 아니라, 자신(예외가 발생할 가능성이 있는 메서드)을 호출한 메서드에게 예외를 전달하여 예외처리를 떠맡기는 것이다.

https://ej-development-note.tistory.com/24

 

 

인터페이스 vs 추상 클래스

 

추상클래스는 인터페이스와 유사하다. 이들은 객체화할 수 없고 주로 구현이 안 된 메소드들로 이루어진다. 하지만 추상 클래스에서는 일반적인 필드도 선언할 수 있으며, 일반적인 메소드도 정의할 수 있다. 인터페이스에서 모든 메소드는 public, abstract가 된다. 자바에서는 하나의 클래스만 상속받을 수 있지만 여러 개 인터페이스를 동시에 구현할 수 있다.

 

1. 추상클래스

만약 관련된 클래스들 사이에서 코드를 공유하고 싶다면 추상 클래스를 사용하는 것이 좋다.

공통적인 필드나 메소드의 수가 많은 경우, 또는 public 이외의 접근 지정자를 사용해야 하는 경우에 추상 클래스를 사용한다.

정적이 아닌 필드나 상수가 아닌 필드를 선언하기를 원할 때 사용한다.

 

2. 인터페이스

관련 없는 클래스들이 동일한 동작을 구현하기를 원할 때 사용한다. 예를 들어서 Comparable과 Cloneable과 같은 인터페이스는 관련없는 클래스들이 구현한다.

특정한 자료형의 동작을 지정하고 싶지만 누가 구현하든지 신경쓸 필요가 없을 때 사용한다.

다중 상속이 필요할 때 사용한다.

 

 

PreparedStatement


명령어를 미리 준비를 하고 준비가 끝나면 명령을 실행하게 되어있으며, 안전하고 쉽게 사용할수 있는 객체이다.
문자열이든 숫자든 '?' 하나로 표현가능하다.
PreparedState를 사용하면 구문 분석(parse)의 결과를 캐싱해서 과정을 생략할 수 있으므로 성능이 향상된다.
PreparedStatement가 SQL Injection을 방어할 수 있다고 한다.

 

*Statement 클래스
- SQL 구문을 실행하는 역할
- 스스로는 SQL 구문 이해 못함(구문해석 X) -> 전달역할
- SQL 관리 O + 연결 정보 X

 

*PreparedStatement 클래스
- Statement 클래스의 기능 향상
- 인자와 관련된 작업이 특화(매개변수)
- 코드 안정성 높음. 가독성 높음.
- 코드량이 증가 -> 매개변수를 set해줘야함
- 텍스트 SQL 호출


파라미터가 동적인 값일 때 PreparedStatement를 사용하는 것이 좋다.
파라미터 값을 특별하게 주지 않는 selectAll()같은 경우에는 Statement 사용해도 된다.

 

public int create(String name, String phoneNumber, String address, double score) {
    String sql = "INSERT INTO restaurant (name, phoneNumber, address, score)"
            + " VALUES (?, ?, ?, ?)";
    try (Connection conn = ConnectionProvider.makeConnection();
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            pstmt.setString(2, phoneNumber);
            pstmt.setString(3, address);
            pstmt.setDouble(4, score);

            return pstmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return 0;
}

 

 

TRANSACTION(트랜잭션)

 

1. 트랜잭션(Transaction)

트랜잭션(Transaction)은 "더이상 분할이 불가능한 업무처리의 단위"를 의미한다.

이것은 하나의 작업을 위해 더이상 분할될 수 없는 명령들의 모음, 즉, 한꺼번에 수행되어야 할 일련의 연산모음을 의미한다.

이와 같이, 데이터베이스와 어플리케이션의 데이터 거래(Transaction)에 있어서 안전성을 확보하기 위한 방법이 트랜잭션인 것이다.

따라서 데이터베이스에서 테이블의 데이터를 읽어 온 후 다른 테이블에 데이터를 입력하거나 갱신, 삭제하는 도중에 오류가 발생하면, 결과를 재반영 하는 것이 아니라 모든 작업을 원상태로 복구하고, 처리 과정이 모두 성공하였을때 만 그 결과를 반영한다.

 

*트랜잭션이 필요한 상황

인출과 입금이 동시에 일어나야하는 상황에서 이 두 과정은 동시에 성공하던지 동시에 실패해야 한다. 

이 과정을 동시에 묶는 방법이 바로 트랜잭션이다.

use my_db;

CREATE TABLE IF NOT EXISTS account (
	id INT PRIMARY KEY AUTO_INCREMENT
    , owner VARCHAR(15) NOT NULL
    , money INT NOT NULL
);

INSERT INTO account (owner, money) VALUES ('내계좌', 10000);
INSERT INTO account (owner, money) VALUES ('you계좌', 15000);
-- drop table if exists account;



-- 계좌 이체
-- 1번 계좌에서 -5000 -> 2번 계좌에 +5000
START TRANSACTION;
BEGIN;
	UPDATE account
	SET money = money - 5000
	WHERE id = 1;

	UPDATE account
	SET money = money + 5000
	WHERE id = 2;
COMMIT; -- ROLLBACK
SELECT * FROM account;

 

2. 트랜잭션 특징

*원자성 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것이다.  

*일관성은 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것이다. 

*독립성은 둘 이상의 트랜잭션이 동시에 실행되고 있을 경우 어떤 하나의 트랜잭션이라도, 다른 트랜잭션의 연산에 끼어들 수 없다는 점을 가리킨다.

*지속성은 트랜잭션이 성공적으로 완료됬을 경우, 결과는 영구적으로 반영되어야 한다는 점이다.

 

3. Commit

Commit이란, 모든 작업들을 정상 처리하겠다고 확정하는 명령어로서, 해당 처리 과정을 DB에 영구 저장하겠다는 의미이며, Commit을 수행하면 하나의 트랜잭션 과정이 종료되는 것이다.
Commit을 수행하면 이전 데이터가 완전히 반영되어 UPDATE된다.

 

4. Roll-back
Roll-back은 작업 중 문제가 발생되어 트랜잭션의 처리 과정에서 발생한 변경사항을 취소하는 명령어이다.
해당 명령을 트랜잭션에게 하달하면, 트랜잭션은 시작되기 이전의 상태로 되돌아간다.
이것은 마지막 Commit을 완료한 시점으로 돌아간다는 말과 상통한다.
즉, Rollback은 Commit하여 저장한 예전 상태를 복구하는 것이다

5. 트랜잭션 예외
모든 명령어에 대하여 트랜잭션의 롤백 명령이 적용되는 것은 아니다.
DDL문(CREATE, DROP, ALTER, RENAME, TRUNCATE)은 transaction의 rollback 대상이 아니다.

 

 

테이블 결합 - JOIN

 

*left outer join, left join

-- 테이블 결합 
select * from restaurant
left outer join menu on restaurant.id = menu.restId;

 

*inner join

-- 테이블 결합 
select * from restaurant
inner join menu on restaurant.id = menu.restId;

 

*join

select * from restaurant join menu;
select * from restaurant, menu;

 

*right outer join

select * from restaurant as a
right outer join menu as b on b.restId = a.id;

 

*테이블 결합 활용 1

use hr;
-- 직원 이름, 속한 부서 이름
select * from employees left join departments on employees.DEPARTMENT_ID = departments.DEPARTMENT_ID;

select A.FIRST_NAME, A.LAST_NAME, B.DEPARTMENT_NAME
    from employees as A
    left join departments as B on A.DEPARTMENT_ID = B.DEPARTMENT_ID
    where B.DEPARTMENT_NAME = 'IT';

 

*테이블 결합 활용 2

-- 'United States of America' 에서 근무하고 있는 직원 목록
-- countries의 COUNTRY_NAME : United States of America // COUNTRY_ID : US
-- countries의 COUNTRY_ID > locations의 LOCATION_ID > departments의 DEPARTMENT_ID > employees

select A.FIRST_NAME, A.LAST_NAME, D.COUNTRY_NAME 
from employees as A
left outer join departments as B on A.DEPARTMENT_ID = B.DEPARTMENT_ID
left outer join locations as C on B.LOCATION_ID = C.LOCATION_ID
left outer join countries as D on C.COUNTRY_ID = D.COUNTRY_ID
where COUNTRY_NAME = 'United States of America';

 

*그룹짓기

select D.COUNTRY_NAME, count(*) 
from employees as A
left outer join departments as B on A.DEPARTMENT_ID = B.DEPARTMENT_ID
left outer join locations as C on B.LOCATION_ID = C.LOCATION_ID
left outer join countries as D on C.COUNTRY_ID = D.COUNTRY_ID
group by D.COUNTRY_NAME;

 

*테이블 결합 활용 3

-- 자기가 속한 부서의 임금 평균보다 높은 임금을 받는 직원 조회하기
select * from departments;
select * from employees;

-- 서브쿼리로 구하기
select * from employees as A 
where A.salary > (select avg(salary) from employees where DEPARTMENT_ID = A.DEPARTMENT_ID);

-- join으로 구하기
select DEPARTMENT_ID, avg(SALARY) as avg
from employees
group by DEPARTMENT_ID;

select A.FIRST_NAME, A.LAST_NAME, A.SALARY, B.avg from employees as A
left join (select DEPARTMENT_ID, avg(SALARY) as avg
			from employees
			group by DEPARTMENT_ID) as B on A.DEPARTMENT_ID = B.DEPARTMENT_ID
where A.SALARY > B.avg;

 

 

MySQL View 만들기

 

Views 우클릭 > Create View.. > 내용작성 > Apply

 

 

MySQL Functions 만들기

 

Views 우클릭 > Create Functions.. > 내용작성 > Apply

 

*함수만들기가 안될땐 옵션 변경 
Administration > Status and System Variables 
> System Variables > 검색 창에 아까 복사했던 [ log_bin_trust_function_creators ] 검색 > Value 값을 ON 으로 변경

 

*함수 작성 예시

FUNCTION `hellorepeat`(num INT) 
RETURNS varchar(255)
BEGIN
    DECLARE var1 INT DEFAULT 0;
    DECLARE str VARCHAR(255) DEFAULT "";
    
    WHILE var1 < num DO
        SET str := CONCAT(str, 'hello');
        SET var1 := var1 + 1;
    END WHILE;
    
    RETURN str;
END

DECLARE var1 INT DEFAULT 0; → 변수 선언 & 초기화

:= → 변수 대입 연산

 

 

MySQL  반복문

 

1. WHILE문

WHILE var1 < num DO
    SET str := CONCAT(str, 'hello');
    SET var1 := var1 + 1;
END WHILE;

 

2. REPEAT문 (do-while문과 비슷)

REPEAT
    SET str := CONCAT(str, 'hello');
    SET var1 := var1 + 1;
until var 1>= num END REPEAT;

 

3. LOOP문 (for문과 비슷)

myloop: LOOP
	SET str := CONCAT(str, 'hello');
	SET var1 := var1 + 1;
	IF var1 >= num THEN
		LEAVE myloop;
	END IF;
END LOOP;

 

 

MySQL 조건문

 

CASE문

-- 조건을 따져 null값일때, -1 아닐경우 null로
select menuId, name, price
, CASE WHEN restId is null then -1 end 
from my_db.menu; 

-- 조건을 따져 null값일때, -1 아닐경우 restId // if-else문과 비슷
select menuId, name, price
, CASE WHEN restId is null then -1 else restId end 
from my_db.menu; 

-- 메뉴 테이블 조회, 추가 컬럼으로 10000원 이상의 메뉴이면 '비쌈', 아니면 '적절'
select * from menu;
select *, case when price >= 10000 then '비쌈'
            when price >= 7000 then '적절'
            else '쌈' end as '가격평가'
from menu;

 

 

addBatch()


addBatch는 쿼리 실행을 하지 않고 쿼리 구문을 메모리에 올려두었다가, 실행 명령(executeBatch)이 있으면 한번에 DB쪽으로 쿼리를 날린다. Array Processing 기능을 활용하면 한 번의 SQL 수행으로 대량의 로우를 동에 insert/update/delete 할 수 있다.

 

 

Caching

 

캐슁이란 저장한다는 뜻이다. 컴퓨팅에서 캐슁이란 오랜시간이 걸리는 작업의 결과를 저장해서 시간과 비용을 필요로 회피하는 기법을 의미한다. 캐슁은 고성능 에플리케이션을 만드는데 가장 중요한 요소 중의 하나다. 

 

 

데이터 무결성

 

데이터 무결성은 데이터의 정확성, 일관성, 유효성이 유지되는 것을 의미한다. 여기서 정확성이란 중복이나 누락이 없는 상태를 뜻하고, 일관성은 원인과 결과의 의미가 연속적으로 보장되어 변하지 않는 상태를 뜻한다. 

만약 데이터베이스에서 데이터 무결성 설계를 하지 않는다면 테이블에 중복된 데이터 존재, 부모와 자식 데이터 간의 논리적 관계 깨짐, 잦은 에러와 재개발 비용 발생 등과 같은 문제가 발생할 것이다.

그렇기 때문에 DBMS에서 데이터의 무결성이 유지되는 것은 중요한 사항이며, 주로 데이터에 적용되는 연산에 제한을 두어 데이터의 무결성을 유지한다.

 

 

제약 조건(constraint)

 

1. 제약 조건(constraint)
제약 조건(constraint)이란 데이터의 무결성을 지키기 위해, 데이터를 입력받을 때 실행되는 검사 규칙을 의미한다.
이러한 제약 조건은 CREATE 문으로 테이블을 생성할 때나 ALTER 문으로 필드를 추가할 때도 설정할 수도 있다.
MySQL에서 사용할 수 있는 제약 조건은 다음과 같다.
*NOT NULL
*UNIQUE
*PRIMARY KEY
*FOREIGN KEY
*DEFAULT

2. NOT NULL
NOT NULL 제약 조건을 설정하면, 해당 필드는 NULL 값을 저장할 수 없다.
즉, 이 제약 조건이 설정된 필드는 무조건 데이터를 가지고 있어야 한다.

3. UNIQUE
UNIQUE 제약 조건을 설정하면, 해당 필드는 서로 다른 값을 가져야 한다.
즉, 이 제약 조건이 설정된 필드는 중복된 값을 저장할 수 없다.

4. PRIMARY KEY
PRIMARY KEY 제약 조건을 설정하면, 해당 필드는 NOT NULL과 UNIQUE 제약 조건의 특징을 모두 가진다.
따라서 이 제약 조건이 설정된 필드는 NULL 값을 가질 수 없으며, 또한 중복된 값을 가져서도 안된다.
이러한 PRIMARY KEY 제약 조건을 기본 키라고 한다.

5. FOREIGN KEY
FOREIGN KEY 제약 조건을 설정한 필드는 외래 키라고 부르며, 한 테이블을 다른 테이블과 연결해주는 역할을 한다.
외래 키가 설정된 테이블에 레코드를 입력하면, 기준이 되는 테이블의 내용을 참조해서 레코드가 입력된다.
즉, FOREIGN KEY 제약 조건은 하나의 테이블을 다른 테이블에 의존하게 만든다.

6. DEFAULT
DEFAULT 제약 조건은 해당 필드의 기본값을 설정할 수 있게 해준다.
만약 레코드를 입력할 때 해당 필드 값을 전달하지 않으면, 자동으로 설정된 기본값을 저장한다.

 

제약조건 활용

 

desc userinfo;
select * from my_db.userinfo;

insert into userinfo (email, firstName, lastName, fullName, visitCount, active)
values('asdf@google.com', '이름1', '성1', '이름1성1', 0, 1);

-- 계산가능한 값은 view나 generated column을 사용하여 컬럼 추가.
insert into userinfo (email, firstName, lastName, fullName, visitCount, active)
values('asdf@google.com', '이름2', '성2', '이름2성2', 0, 1);

-- email 중복 : unique 제약사항으로 해결
insert into userinfo (email, firstName, lastName, fullName, visitCount, active)
values('asdf@google.com', '이름2', '성2', '이름2성2', 0, 1);

-- 행 추가 시 DEFAULT값 설정
insert into userinfo (email, firstName, lastName, fullName)
values('another@google.com', '이름2', '성2', '이름2성2');

-- not null 제약사항으로 해결
insert into userinfo (email, firstName, lastName, fullName, visitCount, active)
values(null, null, null, null, null, null);