관리 메뉴

bright jazz music

blog09: 페이징 처리(QueryDSL) 1 본문

Projects/blog

blog09: 페이징 처리(QueryDSL) 1

bright jazz music 2023. 1. 4. 19:31

@PageableDafault를 컨트롤러에 달아 페이징 관련 파라미터를 받아서그걸 서비스에 넘긴 뒤에 JpaRepository를 사용해서 데이터를 가져오는 작업을 했다.

 

그렇지만 나만의 페이징 클래스를 만들어서, 그 안에서 검증을 거치고 서비스로 넘긴 뒤, 리포지토리에 QueryDSL를 하나 만들어 주고, QueryDSL로 페이징 처리를 하는 방법도 좋다.

 

따라서 여기서는 queryDsl을 사용해서 페이징 처리를 한다.

 

 

 

 

/*build.gradle*/

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.6'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.endofma'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation' /*추가*/

    //gradle 5버전부터 annotationprocessor가 사용 가능해서
    // gradle 레벨에서 컴파일 할 때 필요한 querydsl클래스 파일을 생성할 수 있게 됐다.
    //querydsl 관련 디펜던시
    implementation 'com.querydsl:querydsl-core'
    implementation 'com.querydsl:querydsl-jpa'

    //annotationProcessor : 인식할 타입을 추가함
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
    annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
    annotationProcessor 'jakarta.annotation:jakarta.annotation-api'



    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

classes를 사용해서 빌드.
페이지에서 확인이 가능하였다.

 

 

 

 

 

---------

 

결과적으로 아래와 같이 프로젝트에 build디렉토리가 추가되었다.

우리가 만든 Post라는 엔티티의 쿼리 파일인 QPost가 생성되었다. 이를 통해서 쿼리가 가능하다. 이로서 기본적인 QueryDSL설정 완료

 

package com.endofma.blog.domain;

import static com.querydsl.core.types.PathMetadataFactory.*;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.PathMetadata;
import javax.annotation.processing.Generated;
import com.querydsl.core.types.Path;


/**
 * QPost is a Querydsl query type for Post
 */
@Generated("com.querydsl.codegen.DefaultEntitySerializer")
public class QPost extends EntityPathBase<Post> {

    private static final long serialVersionUID = 959238931L;

    public static final QPost post = new QPost("post");

    public final StringPath content = createString("content");

    public final NumberPath<Long> id = createNumber("id", Long.class);

    public final StringPath title = createString("title");

    public QPost(String variable) {
        super(Post.class, forVariable(variable));
    }

    public QPost(Path<? extends Post> path) {
        super(path.getType(), path.getMetadata());
    }

    public QPost(PathMetadata metadata) {
        super(Post.class, metadata);
    }

}

---------

 

PostRepositoryImpl생성

//querydsl을 쓰려면 JPAQueryFactory를 주입해서 써야한다.
// 이것은 직접 Bean을 만들어서 넣어준다.

 

//QueryDslConfig.java

package com.endofma.blog.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Configuration
public class QueryDslConfig {

    @PersistenceContext
    public EntityManager em;

    @Bean
    public JPAQueryFactory jpaQueryFactory(){
        return new JPAQueryFactory(em);
    }
}

JPAQueryFactory를 주입하기 위한 Bean을 만들었다.

 

 

이제 이것을 주입하자.

 

//PostRpositoryImpl.java

package com.endofma.blog.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class PostRepositoryImpl {

    //querydsl을 쓰려면 JpaQueryFactory를 주입해서 써야한다.
    // 이것은 직접 Bean을 만들어서 넣어준다.

    private final JPAQueryFactory jpaQueryFactory;

//    @RequiredArgsConstructor로 아래 코드 대체
//    public PostRepositoryImpl(JPAQueryFactory jpaQueryFactory){
//        this.jpaQueryFactory = jpaQueryFactory;
//    }

}

 

이제 쿼리를 만들 준비를 하자. 

인터페이스 생성

//PostRepositoryCustom.java

package com.endofma.blog.repository;

import com.endofma.blog.domain.Post;

import java.util.List;

public interface PostRepositoryCustom {
    List<Post> getList(int page);
}

 

이제 이 인터페이스를 PostRepositoryImpl에서 implements하고 overriding해 보

//PostRpositoryImpl.java

package com.endofma.blog.repository;

import com.endofma.blog.domain.Post;
import com.endofma.blog.domain.QPost;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;

import java.util.List;

@RequiredArgsConstructor
public class PostRepositoryImpl implements PostRepositoryCustom{

    //querydsl을 쓰려면 JpaQueryFactory를 주입해서 써야한다.
    // 이것은 직접 Bean을 만들어서 넣어준다.

    private final JPAQueryFactory jpaQueryFactory;

//    @RequiredArgsConstructor로 아래 코드 대체
//    public PostRepositoryImpl(JPAQueryFactory jpaQueryFactory){
//        this.jpaQueryFactory = jpaQueryFactory;
//    }

    @Override
    public List<Post> getList(int page) {
        return jpaQueryFactory.selectFrom(QPost.post)
                .limit(10) //10개만 가져오기
                .offset((long) (page -1) * 10)
                .orderBy(QPost.post.id.desc())
                .fetch();
    }


}

 

//PostRepository.java

package com.endofma.blog.repository;

import com.endofma.blog.domain.Post;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PostRepository extends JpaRepository<Post, Long>, PostRepositoryCustom { //Post 엔티티와 primary key 형식이 들어간다.
//PostRepositoryCustom을 구현하면 postRepositoryImpl의 기능들이 자동으로 주입된다.
    //그렇기 떄문에 PostRepository를 사용하는 PostService에서 사용할 수 있다.
}

 

 

//PostService.java

package com.endofma.blog.service;

import com.endofma.blog.domain.Post;
import com.endofma.blog.repository.PostRepository;
import com.endofma.blog.request.PostCreate;
import com.endofma.blog.response.PostResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
//@RequiredArgsConstructor
public class PostService {

    private final PostRepository postRepository;
    public PostService(PostRepository postRepository){
        this.postRepository = postRepository;
    }

    public void write(PostCreate postCreate) {
        //PostCreate 일반 클래스 ==> Post 엔티티
        Post post = Post.builder()
                .title(postCreate.getTitle())
                .content(postCreate.getContent())
                .build();

        postRepository.save(post);
    }

    //단건 조회
    public PostResponse get(Long id) {

        Post post = postRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 글입니다.")); //있으면 post반환 없으면 에러 반환

        //응답 클래스를 분리
        return PostResponse.builder()
                .id(post.getId())
                .title(post.getTitle())
                .content(post.getContent())
                .build();

    }

//    public List<Post> getList() {
//        return postRepository.findAll();
//    }

    public List<PostResponse> getList(Pageable pageable){

//        return postRepository.findAll(pageable).stream() //pageable
        return postRepository.getList(1).stream() //QueryDsl사용
                .map(PostResponse::new)
                .collect(Collectors.toList());
    }
}
//PostServiceTest.java

package com.endofma.blog.service;

import com.endofma.blog.domain.Post;
import com.endofma.blog.repository.PostRepository;
import com.endofma.blog.request.PostCreate;
import com.endofma.blog.response.PostResponse;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@SpringBootTest
class PostServiceTest {

    @Autowired
    private PostService postService;

    @Autowired
    private PostRepository postRepository;

    @BeforeEach
    void clean(){
        postRepository.deleteAll();
    }

    @Test
    @DisplayName("글 작성")
    void test1() {
        //given
        PostCreate postCreate = PostCreate.builder()
                .title("제목입니다.")
                .content("내용입니다.")
                .build();

        //when
        postService.write(postCreate);

        //then
        Assertions.assertEquals(1L, postRepository.count());
        Post post = postRepository.findAll().get(0);
        assertEquals("제목입니다.", post.getTitle());
        assertEquals("내용입니다.", post.getContent());

    }

    @Test
    @DisplayName("글 1개 조회")
    void test2(){
        //given
        Post requestPost = Post.builder()
                .title("foo")
                .content("bar")
                .build();
        postRepository.save(requestPost);

        //when
        PostResponse response = postService.get(requestPost.getId());

        //then
        Assertions.assertNotNull(response);
        assertEquals(1L, postRepository.count());
        assertEquals("foo", response.getTitle());
        assertEquals("bar", response.getContent());
    }

    @Test
    @DisplayName("글 1페이지 조회")
    void test3(){
        //given
        List<Post> requestPost = IntStream.range(1, 20) //for (int =0; i<30; i++)
                .mapToObj(i -> Post.builder()
                        .title("foo " + i)
                        .content("bar " + i)
                        .build())
                .collect(Collectors.toList());

        postRepository.saveAll(requestPost);


        // sql -> select, limit, offset 알아야 함.

        Pageable pageableRequest = PageRequest.of(0, 5, Sort.Direction.DESC, "id");

        //when
        List<PostResponse> posts = postService.getList(pageableRequest);

       //then
        assertEquals(10L, posts.size());
        assertEquals("foo 19", posts.get(0).getTitle());

    }

}

결과

 

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
22:34:50.420 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
22:34:50.433 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
22:34:50.478 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.endofma.blog.service.PostServiceTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
22:34:50.494 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.endofma.blog.service.PostServiceTest], using SpringBootContextLoader
22:34:50.502 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.endofma.blog.service.PostServiceTest]: class path resource [com/endofma/blog/service/PostServiceTest-context.xml] does not exist
22:34:50.503 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.endofma.blog.service.PostServiceTest]: class path resource [com/endofma/blog/service/PostServiceTestContext.groovy] does not exist
22:34:50.504 [Test worker] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.endofma.blog.service.PostServiceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
22:34:50.505 [Test worker] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.endofma.blog.service.PostServiceTest]: PostServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
22:34:50.568 [Test worker] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.endofma.blog.service.PostServiceTest]
22:34:50.658 [Test worker] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [D:\personal\blog\build\classes\java\main\com\endofma\blog\BlogApplication.class]
22:34:50.660 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.endofma.blog.BlogApplication for test class com.endofma.blog.service.PostServiceTest
22:34:50.801 [Test worker] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [com.endofma.blog.service.PostServiceTest]: using defaults.
22:34:50.801 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
22:34:50.821 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@33a2499c, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@e72dba7, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@33c2bd, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@1dfd5f51, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@3c321bdb, org.springframework.test.context.support.DirtiesContextTestExecutionListener@24855019, org.springframework.test.context.transaction.TransactionalTestExecutionListener@3abd581e, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@4d4d8fcf, org.springframework.test.context.event.EventPublishingTestExecutionListener@610db97e, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@6f0628de, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@3fabf088, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@1e392345, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@12f3afb5, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@4ced35ed, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@2c22a348]
22:34:50.827 [Test worker] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@3a7704c testClass = PostServiceTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@6754ef00 testClass = PostServiceTest, locations = '{}', classes = '{class com.endofma.blog.BlogApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@75459c75, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@d8305c2, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@531c311e, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4b672daa, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@354fc8f0, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@3b5fad2d], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null].

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.6)

2023-01-04 22:34:51.370  INFO 11452 --- [    Test worker] c.endofma.blog.service.PostServiceTest   : Starting PostServiceTest using Java 11.0.12 on DESKTOP-Q7HBM41 with PID 11452 (started by user in D:\personal\blog)
2023-01-04 22:34:51.372  INFO 11452 --- [    Test worker] c.endofma.blog.service.PostServiceTest   : No active profile set, falling back to 1 default profile: "default"
2023-01-04 22:34:52.434  INFO 11452 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-01-04 22:34:52.517  INFO 11452 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 69 ms. Found 1 JPA repository interfaces.
2023-01-04 22:34:53.321  INFO 11452 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-01-04 22:34:53.642  INFO 11452 --- [    Test worker] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-01-04 22:34:53.749  INFO 11452 --- [    Test worker] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2023-01-04 22:34:53.834  INFO 11452 --- [    Test worker] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.14.Final
2023-01-04 22:34:54.110  INFO 11452 --- [    Test worker] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2023-01-04 22:34:54.304  INFO 11452 --- [    Test worker] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2023-01-04 22:34:55.157  INFO 11452 --- [    Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2023-01-04 22:34:55.168  INFO 11452 --- [    Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-01-04 22:34:55.939  WARN 11452 --- [    Test worker] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2023-01-04 22:34:56.375  INFO 11452 --- [    Test worker] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:blog'
2023-01-04 22:34:56.870  INFO 11452 --- [    Test worker] c.endofma.blog.service.PostServiceTest   : Started PostServiceTest in 5.99 seconds (JVM running for 8.53)
2023-01-04 22:34:57.596  INFO 11452 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-01-04 22:34:57.597  INFO 11452 --- [ionShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
2023-01-04 22:34:57.602  WARN 11452 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 90121, SQLState: 90121
2023-01-04 22:34:57.602 ERROR 11452 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-01-04 22:34:57.603  WARN 11452 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 90121, SQLState: 90121
2023-01-04 22:34:57.603 ERROR 11452 --- [ionShutdownHook] o.h.engine.jdbc.spi.SqlExceptionHelper   : Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-214]
2023-01-04 22:34:57.604  WARN 11452 --- [ionShutdownHook] o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'entityManagerFactory': org.hibernate.exception.JDBCConnectionException: Unable to release JDBC Connection used for DDL execution
2023-01-04 22:34:57.604  INFO 11452 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-01-04 22:34:57.610  INFO 11452 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
BUILD SUCCESSFUL in 12s
4 actionable tasks: 2 executed, 2 up-to-date
PM 10:34:58: Execution finished ':test --tests "com.endofma.blog.service.PostServiceTest.test3"'.
Comments