Spring Bean Container


스프링 빈 컨테이너 역할

스프링 객체를 관리한다 : 컨테이너가 스스로 객체를 생성한다

1) @ComponentScan : @Component가 붙은 클래스들을 읽어서 객체로 생성한다

2) @Bean : @Bean을 이용하여 개발자가 생성하는 코드를 작성한다.



@Configuration

-> class 가져올 때 반드시 사용해야함


@Import 

-> configure 파일 가져옴


@Import({DVDConfig.class, DVDPlayerConfig.class})

두가지 클래스 믹싱하는 방법


@Component 종류에는

-> 1. @Controller - @RestController

    2. @Service

    3. @Repository


@RestController : @RestController -> @Controller 안으로 들어가면 @Component 어노테이션이 있다.

@Component 어노테이션이 붙어 있으면 스프링 Bean Container가 모두 객체를 생성한다.(개발자가 직접 new()를 사용하는 것과 같은 역할)


@ComponentScan

-> 루트 패키지 이하의 클래스 중 @Component 어노테이션이 붙은 클래스 검색








https://jhkang-tech.tistory.com/44

DB 테이블을 생성할 때 데이터의 타입을 정의해 주는 것은 아주 중요하다.

연산이 필요한 데이터가 있을 수도 있고, BLOB같이 많은 공간을 사용하는 데이터 타입은 비효율적일 수도 있다.

결국 DB의 저장과 효율을 높이기 위해서는 알맞는 데이터 타입을 사용할 필요가 있으며 테이블의 사이즈를 줄이고 데이터의 처리 속도를 향상 시킬 수 있다.

DEC(6,2) : 소수점 앞의 숫자는 최대 6개, 소수점 뒤의 숫자는 최대 2개를 의미


*VARCHAR와 CHAR의 차이

- VARCHAR는 길이가 변할 수 있으므로(최대 길이는 유효) 길이가 변할 수 있는 데이터의 타입으로 사용하면 유용하다.(공간 절약)

- CHAR 만약 길이가 변하지 않고, 항상 정해진 길이라면 CHAR를 사용할 수 도 있다.


*참고

작은 따옴표를 사용하는 데이터 타입

-char / varchar / date / datetime / time / timestamp / blob

작은 따옴표를 사용하지 않는 데이터 타입

- dec / int

https://cocodo.tistory.com/11?category=739808



자바 데이터베이스 관련 더 찾은 블로그

https://m.blog.naver.com/PostView.nhn?blogId=printf7&logNo=10170263611&proxyReferer=https%3A%2F%2Fwww.google.com%2F



자바에서 데이터베이스로 쿼리문을 전송할 때 사용할 수 있는 인터페이스가 2가지 있다. Statement와 PreparedStatement이다. 둘다 쿼리 전송기능을 가지고 있지만 차이점이 있다. 어떤 점이 차이가 나고, 어느 인터페이스를 사용하는 것이 좋은지 자세하게 알아보자.

공통점


  1. 두 인터페이스 모두 SQL 질의문을 전달하는 역할을 한다.

  2. 사용시 반드시 try~catch문 또는 throws 처리를 해야한다.


Statement (인터페이스)


  1. Statement 객체는 Statement 인터페이스를 구현한 객체를 Connection 클래스의 createStatement( ) 메소드를 호출함으로써 얻어진다.

  2. Statement 객체가 생성되면 executeQuery( ) 메소드를 호출하여 SQL문을 실행시킬 수 있다. 메소드의 인수로 SQL문을 담은 String객체를 전달한다.

  3. Statement는 정적인 쿼리문을 처리할 수 있다. 즉 쿼리문에 값이 미리 입력되어 있어야 한다.



<Connection 인터페이스 API>





PreparedStatement (인터페이스)


  1. PreparedStatement 객체는 Connection 객체의 preparedStatement( ) 메소드를 사용해서 생성한다. 이 메소드는 인수로 SQL문을 담은 String객체가 필요하다.

  2. SQL문장이 미리 컴파일되고, 실행 시간동안 인수값을 위한 공간을 확보할 수 있다는 점에서 Statement 객체와 다르다. 

  3. Statement 객체의 SQL은 실행될 때 매번 서버에서 분석해야 하는 반면, PreparedStatement 객체는 한 번 분석되면 재사용이 용이하다.

  4. 각각의 인수에 대해 위치홀더(placeholder)를 사용하여 SQL문장을 정의할 수 있게 해준다. 위치홀더는 ? 로 표현된다.

  5. 동일한 SQL문을 특정 값만 바꾸어서 여러 번 실행해야 할 때, 인수가 많아서 SQL문을 정리해야 될 필요가 있을 때 사용하면 유용하다.



<Connection 인터페이스 API>





예제



  • 테이블


1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE TEST 
(
  ID VARCHAR2(20NOT NULL 
, PW VARCHAR2(20NOT NULL 
, NAME VARCHAR2(20NOT NULL 
CONSTRAINT TABLE1_PK PRIMARY KEY 
  (
    ID 
  )
  ENABLE 
);
cs



  • DBConnection.java (오라클 연결을 위한 클래스)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DBConnection 
{
    public static Connection dbConn;
    
        public static Connection getConnection()
        {
            Connection conn = null;
            try {
                String user = "scott"
                String pw = "tiger";
                String url = "jdbc:oracle:thin:@localhost:1521:orcl";
                
                Class.forName("oracle.jdbc.driver.OracleDriver");        
                conn = DriverManager.getConnection(url, user, pw);
                
                System.out.println("Database에 연결되었습니다.\n");
                
            } catch (ClassNotFoundException cnfe) {
                System.out.println("DB 드라이버 로딩 실패 :"+cnfe.toString());
            } catch (SQLException sqle) {
                System.out.println("DB 접속실패 : "+sqle.toString());
            } catch (Exception e) {
                System.out.println("Unkonwn error");
                e.printStackTrace();
            }
            return conn;     
        }
}
cs



  • StatementTest.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.sql.Statement;
import java.sql.Connection;
import java.sql.SQLException;
 
public class StatementTest 
{
    public static void main(String args[])
    {
        Connection conn = null// DB연결된 상태(세션)을 담은 객체
        Statement stm = null;  // SQL 문을 나타내는 객체
        
        try {
            conn = DBConnection.getConnection();
            stm = conn.createStatement();
            
            String quary = "INSERT INTO TEST VALUES('id1', 'pw1', 'name1')";
            int success = stm.executeUpdate(quary);
            
            if(success > 0)
                System.out.println("데이터 입력 성공");
            else
                System.out.println("데이터 입력 실패");
 
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        }
    }
}
cs



  • PreparedStatementTest.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
 
public class PreparedStatementTest 
{
    public static void main(String args[])
    {
        Connection conn = null// DB연결된 상태(세션)을 담은 객체
        PreparedStatement pstm = null;  // SQL 문을 나타내는 객체
        
        try {
            
            String quary = "INSERT INTO TEST VALUES(?, ?, ?)";
            
            conn = DBConnection.getConnection();
            pstm = conn.prepareStatement(quary);
            
            // 쿼리에 값을 세팅한다.
            // 여기서 1, 2, 3은 첫번째, 두번째, 세번째 위치홀더 라는 뜻
            pstm.setString(1"id2");
            pstm.setString(2"pw2");
            pstm.setString(3"name2");
            
            int success = pstm.executeUpdate();
            
            if(success > 0)
                System.out.println("데이터 입력 성공");
            else
                System.out.println("데이터 입력 실패");
 
            
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        }
    }
}
cs



  • StatementTest.java 실행결과




  • PreparedStatementTest.java 실행결과





어떤 것을 사용하는 것이 좋은가?


PreparedStatement를 사용하는 것이 좋다. PreparedStatement는 동적인 쿼리문을 처리할 수 있으므로 같은 SQL문에서 값만 변경하여 사용한다던가 인수가 많은 경우에 사용하기 좋다. 또한 미리 컴파일되기 때문에 수행 속도가 Statement보다 빠른 장점이 있다.


Statement 객체는 쿼리 실행시 값에 작은따옴표( ' )가 포함되어 있으면 작은따옴표를 두 개( ' ' ) 표시해야 한다. 예를 들어 입력할 값이 I ' am 이라고 하자. 그러면 쿼리문 작성시에 값을 I ' ' am 이렇게 입력해야 한다. 그러나 PreparedStatement 객체는 작은따옴표 문제를 쿼리 실행시 자동으로 처리하므로 신경쓸 필요가 없다는 장점이 있다.



출처: https://all-record.tistory.com/79 [세상의 모든 기록]

http://rapapa.net/?p=311


Mysql Join 해부(Left, Right, Outer, Inner Join)

Mysql DB를 다룰 때 초보 수준에서 약간 중급으로 넘어가면서 흔히들 많이 어려워 하는 것이 Join 구문입니다.

먼저, 아래와 같은 테이블 두개가 있다고 합시다.

+————+————–+——+
| name | phone | pid |
+————+————–+——+
| Mr Brown | 01225 708225 | 1 |
| Miss Smith | 01225 899360 | 2 |
| Mr Pullen | 01380 724040 | 3 |
+————+————–+——+

+——+——+———————-+
| pid | spid | selling |
+——+——+———————-+
| 1 | 1 | Old House Farm |
| 3 | 2 | The Willows |
| 3 | 3 | Tall Trees |
| 3 | 4 | The Melksham Florist |
| 4 | 5 | Dun Roamin |
+——+——+———————-+

두 테이블은 pid 칼럼으로 엮여 있습니다.

먼저 두 테이블을 pid가 같은 것을 조건으로 일반적인 Join을 걸면 결과는 아래와 같습니다.

 

+———–+————–+———————-+
| name | phone | selling |
+———–+————–+———————-+
| Mr Brown | 01225 708225 | Old House Farm |
| Mr Pullen | 01380 724040 | The Willows |
| Mr Pullen | 01380 724040 | Tall Trees |
| Mr Pullen | 01380 724040 | The Melksham Florist |
+———–+————–+———————-+

pid가 같은 조건이 있는 줄은 두 테이블 모두에서 모조리 나오게 됩니다.
어느테이블이 기준이랄 것이 없이 양쪽에서 줄들이 추가되는 형국이죠. 이 때 서로 같은 것이 존재하지 않는 줄은 아예 출력이 되지 않습니다.

반면, Left 혹은 right join은 기준 테이블, 즉 반드시 출력되는 테이블을 잡아 줍니다.
위의 SQL 구문에서 Left Join을 걸어 보면 아래와 같은 결과가 나옵니다.

+————+————–+———————-+
| name | phone | selling |
+————+————–+———————-+
| Mr Brown | 01225 708225 | Old House Farm |
| Miss Smith | 01225 899360 | NULL |
| Mr Pullen | 01380 724040 | The Willows |
| Mr Pullen | 01380 724040 | Tall Trees |
| Mr Pullen | 01380 724040 | The Melksham Florist |
+————+————–+———————-+

이 때 Left Join이기 때문에 왼쪽 테이블이 기준이 됩니다.
따라서, 왼쪽 테이블의 모든 Row가 결과값에 반드시 한줄 이상 나오는 보장을 받게 됩니다. 왼쪽 테이블(demo_people)에 해당하는 오른쪽 테이블의 pid가 여러개일경우 위와 같이 여러줄이 나옵니다.

반면, right join은 left join과 반대로 기준이 오른쪽 테이블입니다.
오른쪽 테이블은 반드시 한줄 이상 나오는 보장을 받게 되는 것이죠.
결과 값을 한번 보시죠.

 

+———–+————–+———————-+
| name | phone | selling |
+———–+————–+———————-+
| Mr Brown | 01225 708225 | Old House Farm |
| Mr Pullen | 01380 724040 | The Willows |
| Mr Pullen | 01380 724040 | Tall Trees |
| Mr Pullen | 01380 724040 | The Melksham Florist |
| NULL | NULL | Dun Roamin |
+———–+————–+———————-+

왼쪽 테이블(demo_people)에 해당 pid 값이 같은 줄이 없어도,
오른쪽 테이블(demo_property)이 모두 나와야 하기 때문에, null, null 값이 출력되게 된 것입니다.

INNER JOIN은 JOIN과 같고,
LEFT OUTER JOIN은 LEFT JOIN과 같고,
RIGHT OUTER JOIN은 RIGHT JOIN과 같습니다.


데이터베이스 설계 순서는 요구분석 - 개념적설계 - 논리적설계 - 물리적설계 - 구현 순으로 이뤄집니다.




1. 요구조건 분석 / 명세

데이터베이스의 사용자, 사용목적, 사용범위, 제약조건 등에 대한 내용을 정리하고 명세서를 작성합니다.



2. 개념적 설계 (E-R모델)

정보를 구조화 하기 위해 추상적 개념으로 표현하는 과정으로 개념 스키마 모델리오가 트랜잭션 모델링을 병행하고, 요구조건 분석을 통해 DBMS 독립적인 E-R 다이어그램을 작성합니다.



3. 논리적 설계 (데이터 모델링)

자료를 컴퓨터가 이해할 수 있도록 특정 DBMS의 논리적 자료 구조로 변환하는 과정입니다. 관계형 데이터베이스인 경우 이 단계에서 테이블을 설계하고, 정규화 과정을 거치게 됩니다.



2. 물리적 설계 (데이터 구조화)

논리적 구조로 표현된 데이터를 물리적 구조의 데이터로 변환하는 과정입니다. 데이터베이스 파일의 저장 구조 및 액세스 경로, 인덱스의 구조와 저장 레코드의 크기, 순서, 접근 경로 등을 결정하며, 반응시간, 공간활용도, 트랜잭션 처리량을 고려하여 설계를 하여야 합니다.



2. 데이터베이스 구현

앞선 설계 단계에서 도출된 데이터베이스 스키마를 실제 파일로 생성하는 단계입니다. 특정 DBMS에서 데이터베이스 스키마를 생성한 후 데이터를 입력하며, 응용 프로그램에서 사용하기 위한 트랜잭션을 생성합니다. 


첫번째는 OOP에서 interface를 사용하는 이유와 같은 이유로 서비스 부분에 interface를 지정하는 것입니다. 
일반적으로 웹 프로그램에서는 서비스 + DAO까지 하나의 컴포넌트로 외부(Controller)에 제공되기 때문에 인터페이스를 사용하여 대체 가능성 등을 고려하는 것이지요.. 
(구체적인 인터페이스의 장점에 대해서는 다음 분께 패스!!)

두번째는 일반적으로 transaction이나 Exception 처리 등의 AOP 설정이 서비스 경계 부분에 지정되기 때문입니다.

Spring의 경우도 이 부분의 인터페이스화 되어 있지 않으면 CGLIB같은 class를 변경하는 추가적인 설정과 library가 필요합니다.

이는 추가 설정이 필요한 측면도 있고, 내부적으로 복잡하게 동작하기 때문인 것 같습니다.


OOP와 AOP를 제대로 갖추기 위해 쓰는건 맞는데
우리나라 IT 현실에서 이걸 쓰는건 사실 회의적일때가 많네요;;
어차피 스파게티 소스도 넘쳐나게 섞어 쓰고, 정작 저렇게 구현해놓고선 제대로 쓰질 않으니
유명무실한 경우가 참 많죠
이걸 이따위로 쓰려면 왜 이걸 가져왔나...참 한탄스럴때가 있는데 어쩔수 없네요;;


service에서 쓰는건 
스프링에서 AOP구현시 사용하는게
JDK의 기본 프록시인데 
프록시는 Inteface기반으로 동작해서
그냥 저게 싫음 CGLib로 쓰면됨
어짜피 스프링도 CGLib는 3버전이후로는 포함되어 있음

인터페이스 자체의 사용 이유는 그냥 규약이 필요할때 쓰면됨

+ Recent posts