지석이의 일기
H2 DB + QueryDsl 테스트 해보자 본문
간단한 프로젝트를 테스트 하기 위해 DB를 설치하고 설정하기가 여간 귀찮지 않을 수 없다.
물론 추후에 배울 도커를 사용한다면 바로 DB환경을 만들 수 있겠지만, 그건 또 서버가 있어야 가능한 소리이다.
그래서 바로 설정이 가능한 H2 데이터 베이스를 사용 하자.
H2 데이터 베이스는 간단하게 말하자면 내가 지금 작동중인 프로젝트 메모리 안에 작은 경량 DB를 만들어 그 안에서 사용하는것이다.
그러므로 매우 가볍고(경량화), 매우 빠르고(고성능) 라는 장점이 있다.
물론 단점으론, 큰 프로젝트에는 사용하지 못하고, 일관성이 유지 되기 힘들다는 점이 있다고 한다.
그러므로 테스트로만 사용하고 실질적인 프로젝트에는 다른 DBMS를 사용하자!
아래는 인터넷에서 찾아 검색한 H2의 장단점 요약이다.
장점:
경량화: H2는 매우 작은 크기의 라이브러리 (약 2MB)로, 복잡한 설치 과정 없이 간단하게 사용할 수 있습니다.
고성능: H2는 메모리 데이터베이스로서 빠른 데이터 처리 속도를 제공합니다. 따라서 작은 규모의 프로젝트에서 뛰어난 성능을 발휘합니다.
다양한 모드 지원: H2는 임베디드 모드와 서버 모드 등 다양한 동작 모드를 지원합니다. 이를 통해 사용자의 환경에 맞게 유연하게 설정할 수 있습니다.
단점:
일관성 문제: H2는 다수의 동시 사용자가 있을 때 일관성(Consistency)을 유지하는 데 어려움이 있을 수 있습니다. 이는 트랜잭션 처리에서 문제를 일으킬 수 있습니다.
대용량 데이터 처리 제한: H2는 중대형 규모의 데이터베이스에 비해 많은 양의 데이터를 처리하는 데 제한이 있는 편입니다.
기본적으로 H2는 프로젝트를 띄운 뒤에 종료 시, 저장된 데이터가 모조리 삭제된다.
계속 데이터를 살리기 위해서는 디스크 기반의 모드에서 추가 작업을 해야하는데, 그 정도 까지 할꺼면 그냥 다른 DBMS를 쓰자.
Gradle 추가
gradle에 QueryDsl을 설치하기에는 쫌 많은 작업이 필요하다. 의존성 주입에 h2도 같이 넣어준다.
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.15'
id 'io.spring.dependency-management' version '1.1.3'
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' // Querydsl 플러그인 추가
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Spring Boot Starter Data JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// H2 Database
runtimeOnly 'com.h2database:h2'
// Querydsl 관련 의존성
implementation 'com.querydsl:querydsl-jpa:5.0.0'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0'
}
//querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
compileQuerydsl{
options.annotationProcessorPath = configurations.querydsl
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
querydsl.extendsFrom compileClasspath
}
//querydsl 추가 끝
application.properties 에 아래와 같이 넣어보자.
# H2 Database 설정
spring.datasource.url=jdbc:h2:mem:testdb;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=jiseok
spring.datasource.password=jiseok
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# Querydsl 설정
spring.jpa.properties.hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
프로젝트 구조는 다음과 같다.
QueryDslConfig에서 entitymanager를 bean 등록해준다.
@Configuration
public class QueryDslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
RestController에서 단순 데이터 접수 창구를 만들어준다.
@org.springframework.web.bind.annotation.RestController
@RequiredArgsConstructor
public class RestController {
private final RestService restService;
@RequestMapping("/GetAllUserCnt")
public int GetAllUserCnt(){
int cnt = restService.GetAllUserCnt();
return cnt;
}
@RequestMapping("/UserSaveProc")
public long UserSaveProc(String name){
// 방금 삽입한 유저의 pk번호가 반환된다.
long userId = restService.UserSaveProc(0, name);
return userId;
}
@RequestMapping("/UserSearch")
public List<User> UserSearch(User userSearch){
List<User> userlist = restService.UserSearch(userSearch);
return userlist;
}
}
service 에서는 service 역활을 해준다.
@org.springframework.stereotype.Service
@RequiredArgsConstructor
public class RestService {
private final RestInterface restInterface;
public int GetAllUserCnt(){
return (int)restInterface.GetAllUserCnt();
}
public long UserSaveProc(long userid , String name) {
//이름만 받고 나이는 랜덤.
User user = new User(userid, name, (int) (Math.random()*100));
User result = restInterface.save(user);
return result.getId();
}
public List<User> UserSearch(User userSearch) {
return restInterface.UserSearch(userSearch);
}
}
RestInterface에서 기본 JPA 레파지토리와 새로 만든 Querydsl용 custom을 상속 받아준다.
@Repository
public interface RestInterface extends JpaRepository<User, Long>, RestInterfaceCustom {
}
JpaRepository은 기본으로 제공되는 것이며, RestInterfaceCustom은 새로 만들어줘야한다.
public interface RestInterfaceCustom {
long GetAllUserCnt();
List<User> UserSearch(User userSearch);
}
@Repository
public class RestInterfaceCustomImpl implements RestInterfaceCustom {
private final JPAQueryFactory jpaQueryFactory;
public RestInterfaceCustomImpl(JPAQueryFactory jpaQueryFactory) {
this.jpaQueryFactory = jpaQueryFactory;
}
@Override
public long GetAllUserCnt(){
QUser qUser = QUser.user;
return jpaQueryFactory
.select(qUser.count())
.from(qUser)
.fetchOne();
}
@Override
public List<User> UserSearch(User user) {
QUser qUser = QUser.user;
BooleanBuilder builder = new BooleanBuilder();
if (user.getName() != null) {
builder.and(qUser.name.eq(user.getName()));
}
if (user.getAge() != 0) {
builder.and(qUser.age.eq(user.getAge()));
}
return jpaQueryFactory
.select(qUser)
.from(qUser)
.where(builder)
.fetch();
}
}
저기서 주구장창 사용하는 User 모델은 아래와 같다.
@Entity
@Data
@Table(name = "TB_USER")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
public User(long ID, String name, int age) {
this.id = ID;
this.name = name;
this.age = age;
}
public User() {
}
}
H2 DB구조에 의해 프로젝트 구동시 ,TB_USER라는 테이블이 생성되고, 유저 생성시 인메모리식으로 등록된다.
github uri : https://github.com/choichoi1233/practice1
'Java' 카테고리의 다른 글
ControllerAdvice을 활용해 전역 CustomException을 설정하자 (0) | 2024.01.15 |
---|---|
스프링부트 와 React 연동 (0) | 2023.11.22 |
Java Stream연습 2 (0) | 2023.11.08 |
Java Stream연습 1 (1) | 2023.11.01 |
인텔리 제이(Intelli J)를 써보자. + Spring boot web 구동 (0) | 2023.10.15 |