🔶Database
🔶Lambda
🔶application.properties
🔶Spring
≣ 목차
/ 오늘의 TIL /
Database
Spring <-> Database 연결
application.yml 작성
url에 사용할 database를 작성한다. 하단 예제에서는 library database를 사용했다.
spring:
datasource:
url: "jdbc:mysql://localhost/library"
username: "root"
password: ""
driver-class-name: com.mysql.cj.jdbc.Driver
새로운 database를 생성하고 싶다면 'create database `데이터베이스명`' 을 작성한다.
'use `데이터베이스명`'으로 해당 데이터베이스를 사용한다.
JdbcTemplate
사용하는 클래스의 생성자를 만들어서 JdbcTemplate를 DI해준다.
- insert, update, delete: jdbcTemplate.update(sql, parameter)
- sql의 변경사항을 저장한다.
- 데이터의 변경이 있을 때 update를 사용한다.
- select: jdbcTemplate.query(sql, new RowMapper<T>)
- RowMapper: 쿼리의 결과를 받아 객체로 반환한다. (익명 클래스 -> 람다식 변경 가능)
- mapRow 메서드를 이용해서 실제 값(필드명)을 ResultSet을 통해 가져와 객체를 반환할 수 있다.
- select 결과가 있는 경우 0으로 반환된다. (List로 반환된다.)
jdbcTemplate.query(sql, (rs, rowNum) -> 0);
Lambda
[키워드]
익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스
* 함수형 프로그래밍
함수의 순수성과 불변성을 강조한다.
- 순수 함수 (Pure Function):
- 순수 함수는 동일한 입력에 대해 항상 동일한 출력을 반환하며, 함수 외부의 상태를 변경하지 않습니다.
- 부작용이 없기 때문에 테스트와 디버깅이 용이합니다.
- 불변성 (Immutability):
- 함수형 프로그래밍에서는 상태가 변경되지 않으며, 모든 데이터는 불변입니다.
- 변수는 한번 할당되면 변경되지 않고, 새로운 값을 생성할 때는 기존 값을 복사하여 새로운 객체를 만듭니다.
- 고차 함수 (Higher-Order Function):
- 고차 함수는 함수를 인자로 받거나 함수를 반환하는 함수입니다.
- 예를 들어, map, filter, reduce와 같은 함수는 고차 함수입니다.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class FunctionalProgrammingExample {
public static void main(String[] args) {
// 순수 함수 예제
Function<Integer, Integer> addTen = x -> x + 10;
// 고차 함수 예제 (map 사용)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.stream()
.map(x -> x * 2)
.collect(Collectors.toList());
// 불변성 예제
System.out.println(doubled); // 출력: [2, 4, 6, 8, 10]
System.out.println(numbers); // 출력: [1, 2, 3, 4, 5] (원본 리스트는 변경되지 않음)
}
}
* @FunctionalInterface: 컴파일러가 해당 인터페이스가 정확히 하나의 추상 메서드를 가지는지 검증한다. 함수형 프로그래밍을 더 안전하고 명확하게 사용할 수 있도록 도와준다.
* 스트림: 데이터 처리 파이프라인을 사용하여 코드를 더 간결하고 명확하게 만들어준다. 특히, 병렬 처리 같은 성능 최적화를 할 때 스트림이 유용하다.
* 메소드 레퍼런스: 이미 존재하는 메소드를 직접 참조하여 람다 표현식을 만들지 않고도 함수형 인터페이스에 구현체를 생성할 수 있다.
종류 / 문법
1. 정적 메소드 레퍼런스 - 클래스명::정적메소드명
// 람다식
Function<String, Integer> parseInt = s -> Integer.parseInt(s);
// 정적 메소드 레퍼런스로 변환
Function<String, Integer> parseIntRef = Integer::parseInt;
2. 인스턴스 메소드 레퍼런스 - 객체명::인스턴스메소드명
// 람다식
BiFunction<String, String, Boolean> startsWith = (str, prefix) -> str.startsWith(prefix);
// 인스턴스 메소드 레퍼런스로 변환
BiFunction<String, String, Boolean> startsWithRef = String::startsWith;
3. 생성자 레퍼런스 - 클래스명::new
// 람다식
Supplier<StringBuilder> stringBuilderSupplier = () -> new StringBuilder();
// 생성자 레퍼런스로 변환
Supplier<StringBuilder> stringBuilderSupplierRef = StringBuilder::new;
람다식이 등장한 이유
람다식은 익명 함수를 표현하기 위해 사용된다.
간결하고 명확하게 작성할 수 있고 일회성 함수를 편리하게 사용하기 위해 등장했다.
람다식과 익명 클래스 간의 관계
익명 클래스: 기존 클래스를 확장하거나 인터페이스를 구현할 수 있으며, 메서드를 오버라이드할 수 있다.
람다식: 함수형 인터페이스(하나의 추상 메서드를 가진 인터페이스)를 구현할 때 사용된다. 익명 클래스보다 간단한 문법을 제공한다.
- 문법의 간결함: 람다식은 익명 클래스에 비해 문법이 간결하다. 코드가 간단해지고 가독성이 높아진다.
- 타입 제한: 람다식은 함수형 인터페이스만 구현 가능하지만, 익명 클래스는 여러 메서드를 가진 인터페이스나 추상 클래스도 구현할 수 있다.
- this 참조: 익명 클래스(익명 클래스 자체), 람다식(람다식을 포함하는 클래스의 인스턴스)
람다식의 문법
매개 변수가 하나일 경우는 소괄호를 생략할 수 있다.
(매개변수 목록) -> { 함수 본문 }
Spring
application.properties
설정을 통해 jdbcTemplate로 진행한 sql query를 확인할 수 있다.
#jdbcTemplate sql log
logging.level.org.springframework.jdbc=debug
제어의 역전(IoC) + 의존성 주입(DI)
IoC(Inversion Of Control): 스프링 컨테이너가 제어권을 가진다.
DI(Dependency Injection): 스프링 컨테이너가 등록되어있는 스프링 빈을 선택해서 넣어준다.
Repository가 interface이므로, 여러 개의 repository 구현체가 스프링 빈으로 등록되어 있다면
@Primary 어노테이션을 통해 어떤 repository를 service에서 DI 받을지 결정하는 것이 필요하다.
@Controller <-> @Service <-> @Repository (interface)
스프링 컨테이너가 제어권을 가지고 있다.
서비스 객체가 new로 Repository를 선택하지 않는다.
빈 등록하기
스프링 빈 이름은 클래스명의 앞 글자만 소문자로 바뀌어서 등록된다.
AppleService -> appleService
위치에 맞게 함께 선언해서 빈을 등록한다.
클래스: @Configuration
메서드: @Bean
* @Configuration + @Bean 조합은 외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다. (ex) JdbcTemplate)
* @Component -> @Controller, @Service, @Repository... 조합은 개발자가 직접 만든 클래스를 스프링 빈으로 등록할 때 사용한다.
빈 주입하기
- 생성자 + (@Autowired) (권장)
- setter + @Autowired -> 보안 취약
- 필드 + @Autowired -> 테스트를 어렵게 만드는 요인
@Qualifier("스프링 빈 이름"): 여러 개의 후보 구현체가 있을 때, 하나를 특정해서 주입하고 싶은 경우 사용한다.
또는 @Qualifier("이름") 동일한 "이름"을 구현체와 호출 Controller에 같이 사용하면 서로 연결된다. (사용/등록 모두 가능)
'Blog > TIL' 카테고리의 다른 글
[240530] 도메인 연관 관계의 중요성 (0) | 2024.05.30 |
---|---|
[240529] 직접 해봐야 안다 (0) | 2024.05.29 |
[240527] 코딩테스트 다다익선 (0) | 2024.05.27 |
[240526] API 개발하기 (0) | 2024.05.26 |
[240524] 수학 지식을 넓히자 (0) | 2024.05.24 |
댓글