SPRING
CS 공부
Bean/Component 어노테이션
@Bean, @Component 어노테이션은 스프링에서 빈(Bean)으로 등록하기 위한 어노테이션이다.
하지만 둘의 용도가 다르다.
@Component 어노테이션 @Component(value="mystudent")
- 개발자가 직접 생성한 클래스를 빈으로 등록하는 경우
- 클래스 수준에서 사용되며 해당 클래스가 구성 요소(Component) 임을 나타내서 Bean으로 등록
- Component 어노테이션이 붙은 클래스는 스프링 콘텍스트에 등록되어, 다른 클래스에서 이를 참조할 수 있다.
- @Controller, @Service, @Repository 어노테이션들은 @Component 어노테이션의 구체화된 형태이다.
@Bean 어노테이션 @Configuration @Bean(name="myarray")
- 개발자가 집접 제어가 불가능한 외부 라이브러리 등을 Bean으로 만들 때 사용
- 메서드 수준에서 사용되며 해당 메서드가 스프링 빈 객체를 생성하여 반환하는 메서드임을 나타낸다.
- Bean 어노테이션이 붙은 메서드는 해당 빈 객체를 생성하는 메서드로 스프링 콘텍스트에 된다.
- @Configuration
- 해당 클래스에서 1개 이상의 Bean을 생성하고 있음을 명시
- 그래서 @Bean 어노테이션을 사용하는 클래스는 반드시 @Configuration과 함께 사용되어야 한다.
@Component vs @Bean
- @Component 어노테이션은 스프링이 자동으로 빈을 생성하고 등록하지만, @Bean 어노테이션은 개발자가 작성한 Method를 통해 반환되는 객체를 Bean으로 만드는 것이다.
- @Component 어노테이션은 다른 어노테이션들의 부모 어노테이션으로 사용된다. @Controller, @Service, @Repository 어노테이션은 모두 @Component 어노테이션을 상속받아 모두 스프링 컨텍스트에 빈으로 등록된다.
+) @Qualifier("Bean이름") , @Autowired , 컴포넌트를 사용한 Bean의 의존성 주입 방법
이 외에도 여러 개..
참고, 출처 : Spring - @Bean 어노테이션과 @Component 어노테이션(DI) - 2
@Component와 @Bean, @Autowired 어노테이션 알아보기
SQL
SQL조인 시에 일치하지 않는 데이터도 0으로 출력하고 싶은 경우가 있다 이경우에는 left outer join을 이용하여 해결할 수 있다.
SELECT o.id, o.customer_name, o.order_date, COUNT(oi.id)
FROM orders AS o
LEFT OUTER JOIN order_items AS oi
ON o.id = oi.order_id
GROUP BY o.id, o.customer_name, o.order_date;
진짜 어떻게 SQLD까지 봤는데 다 까먹을 수 있는거냐고..(하하🥲)
LEFT JOIN (or LEFT OUTER JOIN)
왼쪽 테이블의 모든 레코드와 오른쪽 테이블에서 일치하는 레코드를 선택하여 조인한다.
만약 오른쪽 테이블에서 일치하는 레코드가 없다면 NULL 값을 반화한다.
RIGHT JOIN (or RIGHT OUTER JOIN)
오른쪽 테이블의 모든 레코드와 왼쪽 테이블에서 일치하는 레코드를 선택하여 조인한다.
만약 왼쪽 테이블에서 일치하는 레코드가 없다면 NULL 값을 반화한다.
FULL OUTER JOIN (or FULL JOIN, or OUTER JOIN)
왼쪽 테이블과 오른쪽 테이블에서 일치하는 모든 레코드를 선택하여 조인한다.
만약 왼쪽 테이블이나 오른쪽 테이블에서 일치하는 레코드가 없다면 NULL 값을 반화한다.
+) 만약 null일때 0으로 출력하고 싶은 경우
IFNULL(확인할 값, value): 확인할 값이 null이면 value를, 확인할 값이 null이 아니면 해당 값이 출력된다.
COALESCE(value1, value2, value3): value1, value2, value3 중에서 NULL이 아닌 값이 있는 첫 번째 값을 반환하며, 만약 모든 값이 NULL인 경우에는 NULL을 반환한다.
-- COALESCE
SELECT COALESCE(NULL, 0, 1); -- 0
-- IFNULL
SELECT IFNULL(NULL, 0); -- 0
참고 ,출처 :
https://leejinseop.tistory.com/19
ALGO(PS)
코드 트리에 있는 코드트리 빵이라는 문제를 풀었다.
package 백준.구현;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class 코드트리_빵 {
private static class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
private static class Human extends Point {
int idx;
Human(int x, int y, int idx) {
super(x, y);
this.idx = idx;
}
}
private static final int[][] dirs = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
private static int n, m;
private static int[][] map;
private static final ArrayList<Point> store = new ArrayList<>(); // 각 사람이 가고자 하는 편의점 위치
private static boolean[] alreadyFind;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
boolean[][][] visited = new boolean[m][n][n]; // 0번은 토탈, 1-2-3- 사람
map = new int[n][n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
if (Integer.parseInt(st.nextToken()) == 1)
map[i][j] = 1; // 게스트 하우스 위치 있음
}
}
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken()) - 1;
int y = Integer.parseInt(st.nextToken()) - 1;
store.add(new Point(x, y));
map[x][y] = 2;// 편의점 위치 //못가는 칸은 -1
}
alreadyFind = new boolean[m];
int nowUser = 1;
int time = 0;
Queue<Human> humans = new LinkedList<>();
while (true) {
time++;
// 1 && 2
int sz = humans.size();
for (int i = 0; i < sz; i++) {
// 4방향으로 갈 수 있는 칸으로 모두 진행한다.
Human now = humans.poll();
if (alreadyFind[now.idx])
continue;// 이미 편의점을 찾아 들어갔다.
for (int[] dir : dirs) {
int movedX = now.x + dir[0];
int movedY = now.y + dir[1];
if (movedX < 0 || movedY < 0 || n <= movedX || n <= movedY)
continue;
if (visited[now.idx][movedX][movedY] || map[movedX][movedY] == -1)
continue; // 이미 방문했거나. 갈 수 없는 칸이면
if (map[movedX][movedY] == 2 && movedX == store.get(now.idx).x && movedY == store.get(now.idx).y) {
// 자신이 가고자 하는 편의점을 발견했다.
alreadyFind[now.idx] = true;
map[movedX][movedY] = -1;
}
visited[now.idx][movedX][movedY] = true;
humans.add(new Human(movedX, movedY, now.idx));
}
}
if (checkAllInStore()) break;
// 3
if (time >= nowUser && nowUser <= m) {
// 주변의 가능한 게스트 하우스중 최단거리의 게스트 하우스를 찾는다
Point nowUserP = store.get(nowUser - 1);
Point guestHouse = findGuestHouse(nowUserP);
map[guestHouse.x][guestHouse.y] = -1; // 이제부터 못 다닌다.
humans.add(new Human(guestHouse.x, guestHouse.y, nowUser - 1));
nowUser++;
}
}
System.out.println(time);
}
private static boolean checkAllInStore() {
boolean allInStore = true;
for (int i = 0; i < m; i++) {
if (!alreadyFind[i]) {
allInStore = false;
break;
}
}
return allInStore;
}
private static Point findGuestHouse(Point nowUserP) {
Queue<Point> q = new LinkedList<>();
boolean[][] tmpVisited = new boolean[n][n];
tmpVisited[nowUserP.x][nowUserP.y] = true;
q.add(nowUserP);
while (!q.isEmpty()) {
Point now = q.poll();
for (int[] dir : dirs) {
int movedX = now.x + dir[0];
int movedY = now.y + dir[1];
if (movedX < 0 || movedY < 0 || n <= movedX || n <= movedY)
continue;
if (tmpVisited[movedX][movedY] || map[movedX][movedY] == -1)
continue; // 이미 방문했거나. 갈 수 없는 칸이면
if (map[movedX][movedY] == 1) { // 가장 가까운 곳 발견했다.
return new Point(movedX, movedY);
}
tmpVisited[movedX][movedY] = true;
q.add(new Point(movedX, movedY));
}
}
return null;
}
}
'2023' 카테고리의 다른 글
[0405] TIL (0) | 2023.04.06 |
---|---|
[0404] TIL (0) | 2023.04.05 |
Stomp convertAndSend (0) | 2023.04.02 |
[TIL]0327 : ERD(식별관계),@PrePersist (0) | 2023.03.28 |
[TIL] stomp origin문제, socket에서의 JWT 처리 (0) | 2023.03.24 |
댓글