Ich habe ein Spring Data JPA-Repository, das Hibernate als Provider verwendet. Ich möchte SQL-Anweisungen protokollieren, aber das kann ich nicht erreichen. Ich habe versucht, verschiedene Lösungen:Aktiviere SQL-Statements, die mit Hibernate und Spring Data protokollieren JPA
- Sets showSql auf true in meinem HibernateJpaVendorAdapter
- hinzufügen log4j.logger.org.hibernate.SQL = DEBUG meine log4j.properties Datei (es ist erwähnenswert, dass log4j.logger.org zu erwähnen. hibernate = INFO haben fügen Sie einige Logging-Informationen aber log4j.logger.org.hibernate.SQL = DEBUG tat nicht)
Hier sind meine Klassen und Konfigurationsdateien:
DatabaseConfiguration.java
/**
* 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
/**
* {@link Employer}'s repository
*
* @author dupirefr
*/
@Repository
public interface EmployerRepository extends JpaRepository<Employer, Long> {
}
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
Warum ist es, dass die bisherigen Lösungen nicht funktioniert? Gibt es eine Art Inkompatibilität zwischen Spring Data JPA und Hibernate SQL-Protokollierungskonfiguration?
EDIT: Ich versuchte beide Lösungen in Kommentaren vorgeschlagen, aber keiner von ihnen funktioniert. Ich versuchte auch, die Datenbank zu ändern, die ich verwendete (H2 für HSQL) oder Hibernate Dialekt zu spezifizieren, aber das hat nicht funktioniert. Tatsächlich wird der Hibernate-Dialekt für einige Datenbanken automatisch gefunden, wenn Spring verwendet wird.
EDIT 2: Ich habe versucht, Protokollierungsebene des RootLogger auf TRACE zu ändern. Ich versuche auch explizit einen Schwellenwert für den Appender anzugeben. Und schließlich habe ich versucht, JpaProperties mit showSql = true hinzuzufügen, aber keiner von ihnen hat den Trick gemacht. Ich denke, dass es etwas wirklich Offensichtliches zu tun gibt, dass ich vermisse, um die komplette Situation zu entsperren: -/
EDIT 3: Der Aufruf des Loggers direkt wie im folgenden Test funktioniert. Ich wurde mich fragen, ob es einen Tippfehler oder etwas gibt, das Hibernate daran hindert, den Logger zu benutzen.
@Test
public void delete() {
LoggerFactory.getLogger("org.hibernate.SQL").debug("delete()");
repository.delete(MICROSOFT);
assertNull(entityManager.find(Employer.class, MICROSOFT.getId()));
}
Hier sind die resultierenden Protokolle:
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 [DefaultTe[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'
EDIT 3: ich, was endlich heraus passieren. Ich habe festgestellt, dass bei fehlgeschlagenen Tests SQL-Abfragen in den Protokollen ausgegeben wurden.Und indem ich ein wenig meine Log4j-Eigenschaften abstimmte, sah ich, dass sie wie erwartet vom Hibernate Logger kamen.
Erfolgreiche Vorgänge führten jedoch keine Protokolle aus. Und das, weil sie die Datenbank nicht erreichen. Alles passiert innerhalb des Entity Managers und somit wird kein SQL benötigt. Jetzt weiß ich, dass ich nur ein Problem mit meiner H2-Datenbank habe, die ich herausfinden muss.
Versuch durch Zugabe von 'logging.level.org.hibernate.SQL = DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE' in der porperties Datei und sehen? –
Sie sagten, 'log4j.logger.org.hibernate = INFO' habe etwas Logging hinzugefügt, aber' log4j.logger.org.hibernate.SQL = DEBUG' nicht. Hast du versucht ... 'log4j.logger.org.hibernate = DEBUG'? Oder gibt es oben einen Tippfehler? – dimwittedanimal
@AhmedRaaj: Diese Eigenschaften müssen in einer Spring-Eigenschaftendatei (wie application.properties) enthalten sein. Ich habe keine, ich benutze Spring Boot nicht. Ich habe versucht, log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder = TRACE zu meiner log4j.properties-Datei hinzuzufügen, aber da das Ziel dieses Loggers binierte Parameter anzuzeigen, hatte es keine Wirkung. –