I wish to pass to Hibernate's SessionFactory
hibernate.hbm2ddl.auto=update
and see in log file generated sql statements. Is it possible w/o java coding (know how to achieve the result with SchemaExport, but hope that hibernate has "in box" solution)
You could setup logging to System.out using
SessionFactory sf = new Configuration().setProperty("hibernate.show_sql", "true")
or log4j
log4j.logger.org.hibernate.SQL=DEBUG, SQL_APPENDER
log4j.additivity.org.hibernate.SQL=false
EDIT: This maybe also helpful Hibernate sql logging with values
You can also set a debug breakpoint on
org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(boolean, boolean)
and see how it goes.
Related
I'm building a SpringBoot application with spring-data-jpa. I know how to log all sqls from this question. How to print a query string with parameter values when using Hibernate
But what if I only want to log failed sqls?
There are two options:
Configure sql logging with parameter values. Disable jdbc batching and enable flushing through hibernate means.
Add debug JDBC driver such as p6spy that will more or less do exactly as described above.
First, let's analyze the problem and split the query types into SELECT and INSERT/UPDATE queries.
SELECT queries for them you have the flushing on by default. So when an error occurs you know exactly which query has failed.
INSERT/UPDATE queries, here things get tricky because your flushing will be off and you have query batching which means that first when you run the query it gets delayed. Second, it gets packed up with other unrelated queries, and third, Hibernate may re-order them. So the short answer is that this is not doable for INSERT/UPDATE if you are using hibernate alone.
A solution to your problem needs to do essentially two things:
1. It should log the queries with their parameter values. This can be done the following way:
# logs the SQL statements
log4j.logger.org.hibernate.SQL=debug
# Logs the JDBC parameters passed to a query
log4j.logger.org.hibernate.type=trace
2. The solution needs to disable the batching of queries, otherwise, you will get a bunch of SQLs but you will not know which SQL exactly is the problematic one.
hibernate.jdbc.batch_size=1
Not sure if this will be enough to entirely disable the batching, but you need to find out.
Alternatively, you can use a jdbc driver designed for DEBUG. This would be p6spy driver which has the option to flush every single SQL statement which is exactly what you want.
Here you need to set the autoflush=true configuration parameter to ensure every single sql statement is immediately flushed to the database.
https://p6spy.readthedocs.io/en/latest/configandusage.html
This gives you multiple log entries. In my case this was not welcome.
Here is my solution for it:
dependency net.ttddyy:datasource-proxy:1.6
Wrap Datasource in Spring Configuration
#Bean
public DataSource dataSource() {
return ProxyDataSourceBuilder.create(originalDatasource())
.logQueryBySlf4j(FLF4JLogLevel.DEBUG).build();
}
Write your own LogAppender - here you can filter the logevents, so you can filter i.e for inserts only or failed executions
public class SQLAppender extends AppenderBase
[...]
#Override
protected void append(ILoggingEvent eventObject) {
[...]
}
configure logback.xml
<appender name="mySQLAppender" class="com.my.SQLAppender" >
</appender>
<logger name="net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener" level="DEBUG"\>
<appender-ref ref="mySQLAppender"/>
</logger>
I have a requirement where I need to grab the Insert and Update Native SQL statement being fired and store it in a log table in the DB. Is it possible for me to get the query in eclipselink?
Register your own custom logger that logs to your database rather than to the file system and configure eclipselink.logging.level.sql=FINE in the persistence unit. Then you can piggy-back on the existing solution for logging SQL statements and save them to the log table. See http://wiki.eclipse.org/EclipseLink/Examples/JPA/CustomLogger and https://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging for details.
We are using Hibernate 3 and DB2 running into the:
Invalid parameter: Unknown column name FOO. ERRORCODE=-4460, SQLSTATE=null
problem which is a common problem I see when searching online. Basically, we need to force Hibernate to retrieve columns by column name. An example of a Stack Overflow question is here
If you read Mark Rotteveel's answer he suggests "set the useJDBC4ColumnNameAndLabelSemantics Connection or DataSource property to DB2BaseDataSource.NO (2)"
My question is, how do I this in Hibernate? I cannot find an example of how to set a JDBC property such as this. Does Hibernate have this property built in?
The manual clearly explains how to set JDBC connection properties.
If you use hibernate.properties to configure Hibernate, you add
hibernate.connection.useJDBC4ColumnNameAndLabelSemantics=2
to the file. If you use hibernate.cfg.xml, you add
<property name="connection.useJDBC4ColumnNameAndLabelSemantics">2</property>
to the session-factory element. You can also use org.hibernate.cfg.Configuration.setProperty() method.
Finally, you can simply append the property to the JDBC URL:
jdbc:db2://hostname:port/database:useJDBC4ColumnNameAndLabelSemantics=2;
Named parameters, just like JdbcTemplate from Spring
XML configuration for JDBC connection settings
XML configuration for queries. Something like Hibernate <sql-query>. See Named SQL queries for an example
I'm thinking of trying to build my own, but I thought I'd ask here, maybe it's already been done.
Obviously I don't want to use neither an ORM nor JdbcTemplate.
What about MyBatis?
(source: mybatis.org)
I'am looking for the same thing, meanwhile try out DBUtils Utility:
http://commons.apache.org/dbutils/
Lightweight, open source and no dependencies.
Try JdbcSession from jcabi-jdbc. It's simple (as you want) and requires you to create a java.sql.DataSource before, for example (using BoneCP and H2 database):
BoneCPDataSource source = new BoneCPDataSource();
source.setDriverClass("org.h2.Driver");
source.setJdbcUrl("jdbc:h2:mem:x");
String name = new JdbcSession(source)
.sql("SELECT name FROM user WHERE id = ?")
.set(555)
.select(new SingleHandler<String>(String.class));
I'm looking for way to get the SQL update script when Hibernate automatically updates tables.
I'm using hibernate.hbm2ddl.auto=update in development environment only, and I need SQL script that updates tables for production.
I want these SQL scripts in txt format for revision and potential edit.
How can this be done?
Thanks for any advice.
There are some suggestions and general discussion here.
In a nutshell, you can turn on logging (to standard output):
hibernate.show_sql=true
Alternatively, if you use log4j, you can add this to your log4j.properties file:
log4j.logger.org.hibernate.SQL=DEBUG
Both of these approaches are going to output Hibernate's prepared statements with parameters (so the parameter values themselves are not inline). To get around this, you could use an interceptor like P6Spy. Details on that can be found here.
org.hibernate.cfg.Configuration class has method:
public java.lang.String[] generateSchemaUpdateScript( Dialect, DatabaseMetadata)
what generates the reqiured update script.
I've just implemented this in grails:
configuration = new DefaultGrailsDomainConfiguration(
grailsApplication: grailsApplication,
properties: props)
//this extends hibernate config
Connection c = SessionFactoryUtils.getDataSource(sessionFactory).getConnection(props.'hibernate.connection.username', props.'hibernate.connection.password')
<br/>md = new DatabaseMetadata(c, DialectFactory.buildDialect(props.'hibernate.dialect'))
configuration.generateSchemaUpdateScript(DialectFactory.buildDialect(props.'hibernate.dialect'), md)
)
check SchemaExport script in grails, for further information, it uses hibernate to generate schema.
(I had to implent is as a service because we have external domain model)