Getting DDL Before Updating the Schema in Hibernate Spring Applications - spring

In a Spring-Hibernate application, hibernate.show_sql=true in log4j property file is enough to show to hibernate generated query. But what we have to do if we need the actual sql query.(For production environment i need to observer and verify the query before updating the schema).
What i am going to do is, after the first schema generation in production( by hibernate itself) i dont want hibernate to update the schema(DDL).I want to hijack the alter, update (DDL) queries and after verification i would like to run those scripts manually in DB.
Is there any approach to do that?

Hibernate has build-in a function to enable the logging of all the generated SQL statements to the console. You can enable it by add a show_sql property in the Hibernate configuration file hibernate.cfg.xml. This function is good for basic troubleshooting, and to see what’s Hibernate is doing behind.
hibernate.cfg.xml
show_sql
Enable the logging of all the generated SQL statements to the console
<property name="show_sql">true</property>
format_sql
Format the generated SQL statement to make it more readable, but takes up more screen space.
<property name="format_sql">true</property>
use_sql_comments
Hibernate will put comments inside all generated SQL statements to hint what’s the generated SQL trying to do
<property name="use_sql_comments">true</property>
log4j.properties
log4j.logger.org.hibernate=INFO, hb
log4j.logger.org.hibernate.SQL=DEBUG ## is equivalent to hibernate.show_sql=true
log4j.logger.org.hibernate.type=TRACE ## allows you to see the binding parameters
log4j.logger.org.hibernate.hql.ast.AST=info
log4j.logger.org.hibernate.tool.hbm2ddl=warn
log4j.logger.org.hibernate.hql=debug
log4j.logger.org.hibernate.cache=info
log4j.logger.org.hibernate.jdbc=debug
log4j.appender.hb=org.apache.log4j.ConsoleAppender
log4j.appender.hb.layout=org.apache.log4j.PatternLayout
log4j.appender.hb.layout.ConversionPattern=HibernateLog --> %d{HH:mm:ss} %-5p %c - %m%n
log4j.appender.hb.Threshold=TRACE
log4j.logger.org.hibernate.tool.hbm2ddl=debug
To print the bind parameters as well, add the following to your log4j.properties file:
log4j.logger.net.sf.hibernate.type=debug

Add the following configurations in log4j.properties file
logs the SQL statements
log4j.logger.org.hibernate.SQL=debug
Logs the JDBC parameters passed to a query
log4j.logger.org.hibernate.type=trace
Enable the show sql property in hibernate configuration file as follows.
<property name="show_sql">true</property>
For more details, check the post

Related

How to see the schema sql (DDL) in spring boot?

How can I see the DDL SQL generated by Hibernate for building the schema from the JPA mappings? I am using the embedded HSQL db.
I tried the following and none of them worked in Spring-Boot 1.3.5.RELEASE.
Adding the following to application.properties file
debug=true
spring.jpa.properties.hibernate.show_sql=true
Set org.hibernate.SQL level to debug in logback.xml
Steps listed at http://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html
Those only show me the sql issued by Hibernate for queries. I am looking for the DDL schema sql issued by Hibernate due the following property:
spring.jpa.hibernate.ddl-auto=create-drop
Try with this property and value:
javax.persistence.schema-generation.scripts.action=create
Do not forget to also set this property:
javax.persistence.schema-generation.scripts.create-target=my-schema.sql
From the JPA 2.1 Specifiation, page 370:
javax.persistence.schema-generation.scripts.action
The javax.persistence.schema-generation.scripts.action property specifies
which scripts are to be generated by the persistence provider. The
values for this property are none, create, drop-and-create, drop. A
script will only be generated if the script target is specified. If
this property is not specified, it is assumed that script generation
is not needed or will
In Spring Boot you can define those two properties in your application.properties file:
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=build/my-schema.sql
spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
Here is a blog post about JPA schema generation with further information about these and other properties:
http://www.thoughts-on-java.org/standardized-schema-generation-data-loading-jpa-2-1/

Spring session with JDBC integration

I am new in Spring Session and want to use embedded database to store session information. I follow all the steps in
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession-jdbc.html using spring-session-jdbc of version 1.2.0.but using Spring-web of 3.2.4 only
The following error is shown repeatly:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "spring_session" does not exist 'Position: 13
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:365)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:824)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
... 21 more'
This issue already haunted me for days. Please help.
Here is the xml configuration
<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessi‌​onConfiguration"/>
<jdbc:embedded-database id="dataSource02" type="H2">
<jdbc:script location="classpath:org/springframework/session/jdbc/schema-h2.sql"/>
</jdbc:embedded-database>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource02"/>
</bean>
Your problem stems from the fact that you use multiple data sources, since the provided stacktrace includes PostgreSQL JDBC driver classes while you are configuring a secondary, embedded data source to storing sessions.
Spring Session configuration picks up your primary data source (PostgreSQL) and expects to find session tables there.
I'd suggest you to use your primary data source to store session data, but if you insist on having secondary/embedded data source for that purpose you need to override JdbcOperationsSessionRepository bean provided by JdbcHttpSessionConfiguration#sessionRepository with your own instance which is created using your secondary data source and its appropriate tra saction manager. Note that bean must be named sessionRepository in order to override one from JdbcHttpSessionConfiguration.

Use logback to log SQL parameters in Spring JdbcTemplate

I'm using Logback with Spring JdbcTemplate to log my SQL queries. My configurations contains next line:
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG" />
But this logs only query with wildcards ? without list of parameters.
Here on SO I found a few answers how to achieve parameters logging with log4j. But I don't want to switch to log4j.
So how can I receive parameters list for JdbcTemplate with Logback?
Edit
Actually, I'm using NamedParameterJdbcTemplate, if it matters.
Try this
<logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="TRACE" />
this will show log:
Setting SQL statement parameter value: column index 1, parameter value [1234], value class [java.lang.Integer], SQL type unknown
I usually prefer handling SQL statement logging at the DataSource or JDBC driver level.
I use BoneCP DataSource/Connection Pool library, which include support for statement logging via SLF4J and many other usefull features.
If changing your DataSource/Connection Pool library is not an option, maybe you can use log4jdbc which works as a proxy jdbc driver, which logs statements to SLF4J before calling the actual jdbc driver that talks to the database.
We can use as follow :
org.hibernate.type.descriptor.sql.
See Link: https://thorben-janssen.com/hibernate-logging-guide/

Hibernate changes database change

I am using Struts and Hibernate 2.0 in my project. My database has changed from oracle 10g to Oracle 11g in my project.
Can you please tell me what changes do I need to make in my Hibernate configuration?
Also Are there any changes required in my Java code.
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:#<host>:<port>:<sid></property>
<property name="connection.username">username</property>
<property name="connection.password">password</property>
<property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.show_sql">false</property>
</session-factory>
</hibernate-configuration>
Just update driver (Jar file) to Oracle Database 11g Release 2 JDBC Drivers
Your XML doesn't seem like it was configured to Oracle 10g , it shows MySQL..
Anyways do this to solve your question.
Just change the Driver name and URL i.e connection string and also change the Dialect
search for Oracle Dialect online and don't forget to add Jars!!! :)
If your data access logic is implemented in Hibernate then your code is portable. Meaning you really don’t need to change anything specific to database change in your case apart from Driver if its causing any trouble . For instance, if you are changing database from MYSQL to Oracle then probably need to change dialect part, Connection properties of your hibernate configuration file alone plus your database specific driver.
Hope this is helpful!
Yes you need to change the dialect name. Sorry I am posting another answer as I am not able to add another comment.
Find for Oracle11g dialect name online, Dialects are classes that convert HQL(hibernate query language to actually Database query), it may say ClassNotFoundException, if this happens then just search for the Hibernate jar that has Oracle11g Dialect Class in it. As I am pretty sure that this jar is NOT available with the JDBCDriver jars that ORacle provides to connect to database.
The Dialect Jars are a part of Hibernate

How to switch the datasource dynamically at runtime using AbstractRoutingDataSource?

Requirement:
I have the requirement like to switch the datasource at runtime after receiving the request.
I had read the blog about routing the datasource at runtime in spring3 using the class AbstractRoutingDataSource. Using that we can get the manually defined datasource key's at runtime.
Here in my project, datasources had configured in jetty-env.xml file. Now, i want to retrieve the Database name from DB in some tables like app_config.Using that DB name, i want to switch the database at runtime and also i want to pass the parameters to jetty-env.xml file.
Even I have a problem trying to set datasources from DB. You may like my solution (with annotations instead of xml). Spring 3.1.3 + Hibernate Configuration with annotations and with (Dynamic) AbstractRoutingDataSource
Taking a look at the "EDIT", you can set there any number of static datasources you want) or use them in xml.
Create a new subclass of DriverManagerDataSource, and autowire it a DAO to access table app_config.
Then for example override getUrl() method, and construct the url using a code dbNameParameter that allows to retrieve the database name from app config:
<bean id="parentDataSource"
class="org.springframework.jdbc.datasource.custom.MyDriverManagerDataSource"
abstract="true">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="username" value="sa"/>
</bean>
<bean id="goldDataSource" parent="parentDataSource">
<property name="dbNameParameter" value="gold"/>
</bean>
jetty-env.xml is not meant for that use and is better not used on this use case. It's better to put in jetty-env.xml only the datasource for where table app_config is.
You should store the tenant identifier in a ThreadLocal, supply data source list, configure an AbstractRoutingDataSource to select the data source at run time based on the tenant identifier.

Resources