스프링 부트 : 프로젝트 만들기 부터 쇼핑몰 간단 구현 (Querydsl Maven 설정 )- 1
JDK 필요
- 자바 애플리케이션 개발하고 실행하기 위한 도구 모음.
- 컴파일러 , 런타임 환경 등등 있음
JDK 공급업체 선택
Oracle,Amazon,Azul 등등이 있음 각 공급업체는 JDK의 버전 관리, 보안 업데이트, 지원 등에서 약간의 차이를 가질 수 있습니다.
스프링 부트 버전 3.3.0 선택
필요 의존성
타임리프 , Spring Data JPA , MySQL Driver , H2 Database 선택
- 타임리프 (Thymeleaf):
- 타임리프는 서버 사이드 자바 템플릿 엔진으로, HTML을 만들기 위한 자바 템플릿 엔진입니다.
- Spring 프레임워크와 통합하기 쉽고, HTML 템플릿에서 동적으로 데이터를 렌더링할 수 있습니다.
- 자바와 유사한 문법을 사용하므로 자바 개발자에게 친숙합니다.
- Spring Data JPA:
- Spring Data JPA는 Spring 프레임워크의 일부로, JPA(Java Persistence API)를 사용하여 데이터베이스와의 상호 작용을 단순화하는 기술입니다.
- 개발자는 SQL 쿼리를 직접 작성하지 않고도 데이터베이스와 상호 작용할 수 있습니다. 대신, JPA의 객체 관계 매핑(ORM)을 사용하여 자바 객체와 데이터베이스 테이블 간의 매핑을 정의합니다.
- MySQL Driver:
- MySQL Driver는 MySQL 데이터베이스와 자바 애플리케이션 간의 통신을 위한 JDBC 드라이버입니다.
- JDBC 드라이버는 자바 애플리케이션이 데이터베이스와 통신할 수 있도록 지원합니다. MySQL 데이터베이스와의 연결, 쿼리 실행 및 결과 처리 등을 담당합니다.
- H2 Database:
- H2 Database는 경량의 관계형 데이터베이스 시스템으로, 자바에서 사용할 수 있는 인메모리 및 디스크 기반 데이터베이스입니다.
- 주로 개발 및 테스트 목적으로 사용되며, 단일 파일로 쉽게 배포할 수 있고, 내장된 모드로 사용할 수 있어 애플리케이션의 간단한 데이터 저장소로용됩니다.
그 다음 애플리케이션 환경먼저 설정
18 line은 애플리케이션 구동 시 JPA의 데이터베이스를 초기화 할 수 있음
create,none,create-drop,update,validate 등등 있음
개발 초기에는 create가 좋고 나중에 validate로 변경
운영에서는 사용하면 데이터 다날라가니깐 당연히 사용 안함 ..^^
엔티티는 데이터베이스의 테이블에 대응하는 클래스
enum에는 품절인지 판매중인지 상태값 나타냄 , 상수값 들어감
package com.constant;
public enum ItemSellStatus {
SELL , SOLD_OUT
}
enum 체크 후에 판매중인값만 나오게 가능!
엔티티 매핑을 해주면서 상품 클래스를 만들어줌
@Entity
@Table(name = "item")
@Getter
@Setter
@ToString
@Id
@Column(name = "item_id")
@GeneratedValue(strategy = GenerationType.AUTO) // 기본키 생성하는 구문
private Long id; //상품코드
엔티티 클래스를 정해주고 기본키 생성하는 구문 등등 어노테이션으로 명시한다.
이러고 실행하면 테이블 생성 로그를 확인할 수 있다. ( Mysql 세팅이 되어 있어야지 가능 )
# application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
테스트 환경 만들어주면서 h2데이터베이스 사용할 수 있게 resource에 파일만듬
application-test.properties에 설정
테스트 코드 자동 작성 가능( chat gpt로도 빠르게 작성 가능 )
테스트 코드 작성 후 Dynamic Proxy를 이용해서 객체를 동적으로 생성해주는 것 확인 Dao , xml 필요없음
쿼리 메소드는 find를 많이 사용
List<Item> itemList = itemRepository.findByItemNm("상품1");
테스트 코드에서 쿼리문을 날릴 수 있다.
where 조건절의 이름으로 검색해서 where item_nm = '상품1' 이름을 검색할 수 있다.
JPQL snippet을 이용해서 쿼리문 작성 가능
// And 조건을 이용한 쿼리
List<Person> findByLastNameAndFirstName(String lastName, String firstName);
// Or 조건을 이용한 쿼리
List<Person> findByLastNameOrFirstName(String lastName, String firstName);
// Is, Equals 조건을 이용한 쿼리
List<Person> findByFirstName(String firstName);
// IsNot, Not 조건을 이용한 쿼리
List<Person> findByFirstNameNot(String firstName);
// Between 조건을 이용한 쿼리
List<Person> findByAgeBetween(int minAge, int maxAge);
// LessThan, LessThanEqual 조건을 이용한 쿼리
List<Person> findByAgeLessThan(int age);
List<Person> findByAgeLessThanEqual(int age);
// GreaterThan, GreaterThanEqual 조건을 이용한 쿼리
List<Person> findByAgeGreaterThan(int age);
List<Person> findByAgeGreaterThanEqual(int age);
// IsNull, IsNotNull 조건을 이용한 쿼리
List<Person> findByLastNameIsNull();
List<Person> findByLastNameIsNotNull();
// Like 조건을 이용한 쿼리
List<Person> findByFirstNameLike(String pattern);
// StartingWith, EndingWith, Containing 조건을 이용한 쿼리
List<Person> findByFirstNameStartingWith(String prefix);
List<Person> findByFirstNameEndingWith(String suffix);
List<Person> findByFirstNameContaining(String keyword);
// OrderBy 조건을 이용한 쿼리
List<Person> findByLastNameOrderByFirstNameAsc(String lastName);
// Not, In, NotIn, IgnoreCase 조건을 이용한 쿼리
List<Person> findByLastNameNot(String lastName);
List<Person> findByAgeIn(List<Integer> ages);
List<Person> findByAgeNotIn(List<Integer> ages);
List<Person> findByFirstNameIgnoreCase(String firstName);
이런식으로 메소드 만들어서 사용하면 됨
OR 같은 경우 findBy~~Or이 들어가 있어야 인식이 됨 이렇게 다른 방식으로 사용하면 안됨
-- itemRepository
List<Item> findByItemNmASSItemDetail(String itemNm, String itemDetail);
@Test
@DisplayName("상품명 , 상품 상세설명 OR TEST")
public void findByItemOrItemDetailTest(){
this.createItemList();
List<Item> itemList = itemRepository.findByItemNmASSItemDetail("테스트 상품1" , "테스트 상품 상세 설명 4");
for(Item item : itemList){
System.out.println(item.toString());
}
}
그럼 제대로 작성해보고 테스트
두개의 값이 잘 나온것을 볼 수 있다.
OR 붙이니 자동으로 잘 검색하는걸 볼 수 있음
@Query("select i from Item i where i.itemDetail like %:itemDetail% order by i.price desc")
List<Item> findByItemDetail(@Param("itemDetail") String itemDetail);
JPQL을 사용해서 복잡한 쿼리도 이런식으로 처리 가능 mybatis굳이 사용안해도 이런식으로도 된다.
데이터 베이스 변경 되어도 그거에 맞게 가능...오라클이랑 postgresql 내장 함수가 달라도 이걸로는 통일 가능
querydsl 적용
JPQL 코드 작성 도움 주는 것 아래는 설정
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.3.1</version>
</dependency>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
인식못할 수 있어서 설정해줘야함 QDomain 임포트 안될 때 있음
근데 이렇게 해도 안됨
의존성 추가해보고 hibernate도 추가했는데 Qitem이 생기지 않음 , jarkarta로 생성하면 생기는데 중복돼서 또 들어가서
정상적으로 compile 되지 않음
Compile나면서 삭제도 해보고 clean 다시하고 버전 변경하고 했는데 mvaen 실행시에만 에러..
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
결국 유일하게 찾은게 version지우는건데 지우니깐 compile은 정상작동 하지만 Qitem 생성 X
java를 resources로도 변경해보고 excluded 로도 변경해봄 안됨...
자카르타 하면 생기긴하는데 에러남 Qitem있는데 또 넣는다고
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<!--
<goals>
<goal>process</goal>
</goals>
-->
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
2시간만에 해결
goal이 에러부분에 있어서 주석처리하니 Qitem도 잘생겼고 maven compile시 에러도 떨어지지 않는다.
원래 기본적으로 process를 목표로 동작하는데 저렇게 명시적으로 해서 어딘가 꼬여서 만들어줬던거 한번 더 만들어 준거 같음..