2017-12-26 6 views
6

하이버 네이트를 프로 바이더로 사용하는 스프링 데이터 JPA 리포지토리가 있습니다. 나는 SQL 문을 기록하고 싶지만 그걸 성취 할 수는 없다. 나는 다양한 솔루션을 시도 : 하이버 네이트 및 스프링 데이터로 로깅 SQL 문 활성화 JPA

  • 내 log4j.properties 파일에 log4j.logger.org.hibernate.SQL = DEBUG 추가 내 HibernateJpaVendorAdapter true로

    • 설정 showSql을 (그것은 그 log4j.logger.org을 언급 할 가치가있다.

      DatabaseConfiguration.java: 최대 절전 모드 = 여기

  • 내 클래스와 구성 파일이) 정보는 일부 로깅 정보를 추가 않았지만 log4j.logger.org.hibernate.SQL = DEBUG하지 않았다 912,992,967,
    /** 
    * Database configuration 
    * 
    * @author dupirefr 
    */ 
    @Configuration 
    @Import({BaseConfiguration.class, DatabaseProperties.class}) 
    @EnableJpaRepositories(basePackages = DatabaseConfiguration.REPOSITORIES_PACKAGE) 
    public class DatabaseConfiguration { 
    
        /* 
        * Constants 
        */ 
        public static final String MODEL_PACKAGE = "be.dupirefr.examples.spring.batch.simple.model"; 
        public static final String REPOSITORIES_PACKAGE = "be.dupirefr.examples.spring.batch.simple.repositories"; 
    
        /* 
        * Beans 
        */ 
        @Bean 
        public DataSource dataSource(DatabaseProperties properties) { 
         DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
         dataSource.setUrl(properties.url); 
         dataSource.setUsername(properties.username); 
         dataSource.setPassword(properties.password); 
         dataSource.setDriverClassName(properties.driverClassName); 
    
         return dataSource; 
        } 
    
        @Bean 
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { 
         LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
         entityManagerFactoryBean.setDataSource(dataSource); 
         entityManagerFactoryBean.setPackagesToScan(MODEL_PACKAGE); 
         entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
         return entityManagerFactoryBean; 
        } 
    
        @Bean 
        public PlatformTransactionManager transactionManager(DataSource dataSource) { 
         return new DataSourceTransactionManager(dataSource); 
        } 
    
    } 
    

    database.properties

    # Data source 
    spring.datasource.url=jdbc:h2:mem:test 
    spring.datasource.username=admin 
    spring.datasource.password=admin 
    spring.datasource.driver-class-name=org.h2.Driver 
    

    DatabaseProperties.java

    /** 
    * Database properties 
    * 
    * @author dupirefr 
    */ 
    @Configuration 
    @PropertySource("classpath:be/dupirefr/examples/spring/batch/simple/config/database/database.properties") 
    public class DatabaseProperties { 
    
        /* 
        * Fields 
        */ 
        @Value("${spring.datasource.url}") 
        public String url; 
    
        @Value("${spring.datasource.username}") 
        public String username; 
    
        @Value("${spring.datasource.password}") 
        public String password; 
    
        @Value("${spring.datasource.driver-class-name}") 
        public String driverClassName; 
    
    } 
    

    EmployerRepository.java

    0,123,762,199,115,812 왜 이전의 솔루션이 작동하지 않았다

    EmployerRepositoryIT.java

    /** 
    * {@link EmployerRepository}'s integration test 
    * 
    * @author dupirefr 
    */ 
    @RunWith(SpringRunner.class) 
    @ContextConfiguration(classes = DatabaseConfiguration.class) 
    @Transactional 
    public class EmployerRepositoryIT { 
    
        /* 
        * Constants 
        */ 
        public static final Employer GOOGLE = new Employer(1L, "Google"); 
        public static final Employer MICROSOFT = new Employer(2L, "Microsoft"); 
        public static final Employer APPLE = new Employer(3L, "Apple"); 
    
        /* 
        * Fields 
        */ 
        @Autowired 
        private EmployerRepository repository; 
    
        @Autowired 
        private EntityManager entityManager; 
    
        /* 
        * Setups 
        */ 
        @Before 
        public void setUp() { 
         entityManager.persist(GOOGLE); 
         entityManager.persist(MICROSOFT); 
        } 
    
        /* 
        * Tests 
        */ 
        @Test 
        public void findById_Exists() { 
         assertEquals(GOOGLE, repository.findById(GOOGLE.getId()).get()); 
         assertEquals(MICROSOFT, repository.findById(MICROSOFT.getId()).get()); 
        } 
    
        @Test 
        public void findById_NotExists() { 
         assertFalse(repository.findById(Long.MAX_VALUE).isPresent()); 
        } 
    
        @Test 
        public void findAll() { 
         assertEquals(Arrays.asList(GOOGLE, MICROSOFT), repository.findAll()); 
        } 
    
        @Test 
        public void save() { 
         repository.save(APPLE); 
         assertEquals(APPLE, entityManager.find(Employer.class, APPLE.getId())); 
        } 
    
        @Test 
        public void delete() { 
         repository.delete(MICROSOFT); 
         assertNull(entityManager.find(Employer.class, MICROSOFT.getId())); 
        } 
    
    } 
    

    log4j.properties

    # Appenders 
    ## Console 
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
    log4j.appender.stdout.Target=System.out 
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
    log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n 
    
    # Loggers 
    ## Root 
    log4j.rootLogger=INFO, stdout 
    
    ## Hibernate 
    ### Generic 
    log4j.logger.org.hibernate=INFO 
    ### SQL statements 
    log4j.logger.org.hibernate.SQL=DEBUG 
    

    입니까? Spring Data JPA와 Hibernate SQL 로깅 설정 사이에 어떤 종류의 비 호환성이 있습니까?

    편집 : 두 솔루션 모두 의견에서 제안했지만 어느 것도 작동하지 않았습니다. 나 또한 사용하고 있던 데이터베이스 (HSQL을위한 H2)를 바꾸거나 Hibernate dialect를 지정하려고 시도했지만 작동하지 않았다. 실제로 Hibernate dialect는 Spring을 사용할 때 일부 데이터베이스에서 자동으로 발견됩니다.

    EDIT 2 : rootLogger의 로깅 수준을 TRACE로 변경하려고했습니다. 나는 또한 애플릿의 명시 적으로 임계 값을 지정하려고 시도합니다. 그리고 마지막으로 showSql = true로 JpaProperties를 추가하려고 시도했지만 그들 중 누구도 트릭을 수행하지 않았습니다. 나는 완전한 상황의 잠금을 해제하기 위해 실종되는 것이 명백하다고 생각합니다. -/

    EDIT 3 : 다음 테스트 에서처럼 로거를 직접 호출하면 효과가있었습니다. 나는 오타가 Hibernate가 로거를 사용하는 것을 막는 오타가 있는지 궁금해하게되었다.

    10:33:45,158 INFO DefaultTestContextBootstrapper:257 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] 
    10:33:45,183 INFO DefaultTestContextBootstrapper:206 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext] 
    10:33:45,185 INFO DefaultTestContextBootstrapper:184 - Using TestExecutionListeners: [org.springframework.test[email protected]1f28c152, org.springframewor[email protected]7d907bac, org.springfra[email protected]7791a895, org.springframew[email protected]3a5ed7a6, org.sp[email protected]6325a3ee]10:33:45,376 INFO GenericApplicationContext:589 - Refreshing [email protected]93d195: startup date [Sun Jan 14 10:33:45 CET 2018]; root of context hierarchy 
    10:33:46,187 WARN ConfigurationClassEnhancer:353 - @Bean method BaseConfiguration.propertySourcesPlaceholderConfigurer is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details. 
    10:33:46,448 INFO DriverManagerDataSource:133 - Loaded JDBC driver: org.h2.Driver 
    10:33:46,743 INFO LocalContainerEntityManagerFactoryBean:361 - Building JPA container EntityManagerFactory for persistence unit 'default' 
    10:33:46,798 INFO LogHelper:31 - HHH000204: Processing PersistenceUnitInfo [ 
        name: default 
        ...] 
    10:33:46,922 INFO Version:45 - HHH000412: Hibernate Core {5.2.12.Final} 
    10:33:46,924 INFO Environment:213 - HHH000206: hibernate.properties not found 
    10:33:46,979 INFO Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 
    10:33:47,318 INFO Dialect:157 - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 
    10:33:48,472 INFO LocalContainerEntityManagerFactoryBean:393 - Initialized JPA EntityManagerFactory for persistence unit 'default' 
    10:33:49,422 INFO TransactionContext:105 - Began transaction (1) for test context [[email protected] testClass = EmployerRepositoryIT, testInstance = be.dupirefr[email protected]1460c81d, testMethod = [email protected], testException = [null], mergedContextConfiguration = [[email protected] testClass = EmployerRepositoryIT, locations = '{}', classes = '{class be.dupirefr.examples.spring.batch.simple.config.database.DatabaseConfiguration}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [o[email protected]5b22b970]; rollback [true] 
    10:33:49,468 DEBUG SQL:83 - delete() 
    10:33:49,512 INFO TransactionContext:137 - Rolled back transaction for test context [[email protected] testClass = EmployerRepositoryIT, testInstance = be.dupirefr[email protected]1460c81d, testMethod = [email protected], testException = [null], mergedContextConfiguration = [[email protected] testClass = EmployerRepositoryIT, locations = '{}', classes = '{class be.dupirefr.examples.spring.batch.simple.config.database.DatabaseConfiguration}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]], attributes = map[[empty]]]. 
    10:33:49,516 INFO GenericApplicationContext:989 - Closing [email protected]93d195: startup date [Sun Jan 14 10:33:45 CET 2018]; root of context hierarchy 
    10:33:49,519 INFO LocalContainerEntityManagerFactoryBean:571 - Closing JPA EntityManagerFactory for persistence unit 'default' 
    

    편집 : 3 : 마침내 알아 낸 일이 무엇

    @Test 
    public void delete() { 
        LoggerFactory.getLogger("org.hibernate.SQL").debug("delete()"); 
        repository.delete(MICROSOFT); 
        assertNull(entityManager.find(Employer.class, MICROSOFT.getId())); 
    } 
    

    다음은 결과 로그입니다. 나는 실패한 테스트에서 SQL 쿼리가 로그에서 발행되었다는 것을 알아 차렸다.그리고 약간의 튜닝으로 log4j 프로퍼티는 예상대로 최대 절전 모드 로거에서 나왔다.

    그러나 성공적인 작업은 로그를 발행하지 않았습니다. 그리고 그것들은 데이터베이스에 도달하지 않기 때문입니다. 모든 것이 엔티티 관리자 내에서 발생하므로 SQL이 필요하지 않습니다. 이제 저는 알아야 할 H2 데이터베이스에 문제가 있음을 압니다.

    +0

    시도'logging.level.org.hibernate.SQL = DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE' porperties 파일에서 볼? –

    +0

    당신은'log4j.logger.org.hibernate = INFO'가 약간의 로깅을 추가했지만'log4j.logger.org.hibernate.SQL = DEBUG'는 그렇지 않다고 말했습니까? 해봤 어?'log4j.logger.org.hibernate = DEBUG'? 아니면 위의 오타가 있습니까? – dimwittedanimal

    +0

    @AhmedRaaj : 이러한 속성은 Spring 속성 파일 (예 : application.properties)에 있어야합니다. 나는 스프링 부트를 사용하지 않고있다. log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder = TRACE를 log4j.properties 파일에 추가하려고 시도했지만이 로거의 목표는 바인드 된 매개 변수를 표시하는 것이므로 아무 효과가 없습니다. –

    답변

    1

    제공 한 코드를 살펴본 결과이를 잘랐지 않으므로이 코드를 디버깅하는 방법에 대해 알아 보겠습니다.

    1. 내 첫 번째 답변에 제공된 변경 사항을 그대로 둡니다.

    2. 표시 한 속성 파일이 실제로 로거 구성을 제어하는지 확인하십시오. 예를 들어 출력 형식을 변경하고 예상대로 출력에 영향을 주는지 확인하십시오.

    3. 최대 절전 모드에서 관련 로깅 문을 찾으십시오. 거기에 중단 점을 넣으십시오. 로그 문이 버려지는 위치를 찾을 때까지 디버그하십시오. 구성과 관련된 데이터 구조를 비교하여 잘못된 점을 파악하십시오. 추가하여

    +0

    나는 그것을 시도 할 것이다 :-). 이전에는 언급하지 않았지만 rootLogger의 TRACE 로깅 수준을 설정하면 일부 로그가 추가되었지만 SQL 쿼리는 추가되지 않았습니다. –

    +0

    테스트의 첫 번째 줄에 중단 점을 넣고 org.hibernate.SQL 로거를 가져 오려고했습니다. 잘 구성된 것 같습니다. 나는 여전히 최대 절전 모드 클래스에서 로깅 구문을 얻으려고 시도 하겠지만, 그렇게 쉽게 보이지는 않는다. :-) –

    +0

    나는 더 이상 파고 갈 여유가 없었고, 여전히 해결책이 없다. 그러나 당신이 저에게 준 도움의 양을 감안할 때, 저는이 질문에 대한 현상금을 당신에게 주겠다고 결심했습니다 :-) –

    3

    은 교체 :

    log4j.rootLogger=INFO, stdout 
    

    log4j.rootLogger=TRACE, stdout 
    

    으로 그리고 당신은뿐만 아니라 바인드 변수의 값을 원하는 경우에 가능

    log4j.logger.org.hibernate.type.descriptor.sql=TRACE 
    

    를 추가합니다.

    당신은 당신의 기록이 잘 구성한하지만 펜더는 INFO을 따기되고 SQL 문이 함께 시도 DEBUG

    +0

    그건 실제로 합법적 인 것 같습니다 .-).나는 오늘 밤 그것을 시도하고 결과와 함께 다시와! –

    +0

    방금 ​​시도했지만 작동하지 않았습니다. 그것에 대해서 생각한 것은 단지 루트 로거의 로깅 수준을 변경하고 appender의 임계 값은 변경하지 않기 때문에 (나는 또한 변경하려고 시도했지만 어느 쪽도 작동하지 않았습니다). 시도해 주셔서 감사합니다. –

    +0

    appender의 임계 값을 정확히 알지 못합니다. 루트 로거에 대한 구성을 제외하고 appender에는 appender가 없습니다. –

    1

    에 기록됩니다

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { 
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 
        entityManagerFactoryBean.setDataSource(dataSource); 
        entityManagerFactoryBean.setPackagesToScan(""); 
        entityManagerFactoryBean.setJpaProperties(properties()); 
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
        return entityManagerFactoryBean; 
    } 
    
    private Properties properties() { 
        Properties properties = new Properties(); 
        properties.put("hibernate.show_sql", "true"); 
        properties.put("hibernate.format_sql", "true"); 
        return properties; 
    } 
    

    UPDATE

    내가 가진 너와 비슷한 설정 클래스, 내가 스프링 부트로 업데이트했기 때문에 그 클래스를 삭제하고 모든 설정을 application.properties 파일로 옮겼다. 내 구성 :

    #DataSource 
    spring.datasource.driver-class-name=org.postgresql.Driver 
    spring.datasource.url=jdbc:postgresql://localhost:5432/mydb 
    spring.datasource.username=postgres 
    spring.datasource.password=123456 
    
    #Hibernate 
    spring.jpa.properties.hibernate.show_sql=true 
    spring.jpa.properties.hibernate.format_sql=true 
    spring.jpa.properties.hibernate.jdbc.batch_size=10 
    spring.jpa.properties.hibernate.id.new_generator_mappings=true 
    
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect 
    spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext 
    
    +0

    작동하지 않았다 :-( –

    +0

    내 업데이트를보세요 –

    +0

    당신은 내가 가지고있는 것보다 더 많은 것들이 있습니다 (사투리 또는 세션 컨텍스트), 그러나 문제에 연결된 것들입니까? Dialect는 아닙니다, 스프링에 의해 자동으로 발견됩니다. (그리고 나는 그것을 명시 적으로 명시하려고 시도했다. 아무 것도 변경하지 않았다.) –

    관련 문제