스프링 입문 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 수강 중@SpringBootTest 어노테이션 붙이기 : 스프링 컨테이너와 테스트 함께 실행 (실제 스프링 구동)통합테스트 (integration test) : spring, db 등을 함께 구동하는 테스트단위테스트 (unit test): 이전에 했던대로 컨테이너 없이 기능단위로 테스트하는 것. 통합테스트보다 훨씬 속도가 빠르기 때문에 단위테스트를 잘 만드는 것이 중요함.commit을 해야 반영됨. 바로 반영되는 것처럼 보이는 것들도 사실 auto-commit이 되는 것@transational 어노테이션: 테스트 시작 전 트랜잭션 시작 -> 쿼리 실행 -> 항상 rollback -> DB 변경 없으므로 다음 테스트에 영향 주지 않음 (@Test에 붙었을 때만 rollback. 일반 service 등에 붙었을땐 정상동작)@Commit 어노테이션 붙이기JdbcTemplate, MyBatis 등 라이브러리는 JDBC API의 반복코드 대부분 제거해주지만 sql은 직접 작성해야 함. 여전히 실무에서 많이 사용.SimpleJdbcInsert : 테이블명, 인덱스 컬럼명 받아서 insert query 알아서 생성ORM (Object-Relational Mapping) : 객체와 관계형 데이터베이스 테이블을 매핑하는 기술jpa : 인터페이스만 제공하며 entity 매핑 필요함 => 구현체로 hybernate 사용EntityManager 주입 받아야 함jpql이라는 쿼리 언어 사용 : 객체지향으로 쿼리 작성 가능@Transactional 필요show-sql=true   # jpa가 날리는 sql 쿼리 볼 수 있음
ddl-auto=none  # 테이블 없을 땐 class보고 알아서 테이블도 생성해주지만(create), 현재 있으므로 패스
ALTER TABLE MEMBER ADD PW VARCHAR(20) 실행해 컬럼 맞춰주니 해결됨javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1626)
at org.hibernate.query.Query.getResultList(Query.java:165)
at com.ticktack.homeytest.repository.JpaMemberRepository.findByName(JpaMemberRepository.java:35)
...
at com.ticktack.homey_test.service.MemberServiceIntegrationTest.회원가입(MemberServiceIntegrationTest.java:37)
...
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "MEMBER0.PW" not found; SQL statement:
select member0.id as id1_0, member0.name as name2_0, member0.pw as pw3_0 from member member0 where member0.name=? [42122-200]
...
Querydsl 라이브러리 이용JdbcTemplate, mybatis 등등 섞어서 사용공통 관심 사항(cross-cutting concern) : 여러 메소드, 기능, 파일에 공통적으로 적용해야 할 사항핵심 관심 사항 (core concern) : 서비스 핵심 로직공통 관심 사항과 핵심 관심 사항의 분리@Aspect
@Component // spring bean으로 등록
public class TimeTraceAop {
	@Around("execution(* com.ticktack.homey_test..*(..))") // 패키지 모든 곳에 적용 가능 (aop around로 검색)
	public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
		long start = System.currentTimeMillis();
		System.out.println("START : " + joinPoint.toString());
		// START : execution(List org.springframework.data.jpa.repository.JpaRepository.findAll())
		
		try {
			return joinPoint.proceed(); // 여기에서 기존 서비스 로직 등 실행되는 듯
		} finally { // try 이후 실행
			long finish = System.currentTimeMillis();
			long timeMs = finish - start;
			System.out.println("END : " + joinPoint.toString() + "  " + timeMs + "ms");
			// END : execution(String com.ticktack.homey_test.Controller.MemberController.list(Model))  222ms
		}
	}
}