I have a little issue with my hibernate logging configuration.
In our application, we have two threads trying to put, concurrently, a lock on each row of Database table.
sometimes, one of those threads tries to lock a row that’s already locked. This error is thrown :
[2/24/12 15:00:34:492 CET] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 54, SQLState: 61000
[2/24/12 15:00:34:496 CET] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions ORA-00054: resource busy and acquire with NOWAIT specified
these lines are put in the SystemOut.log files. I’m trying to put them in another file. So in my Log4j configuration file, I created a new appender like this :
<appender name="JDBCExceptionReporter" class="org.apache.log4j.RollingFileAppender">
<param name="Encoding" value="UTF-8"/>
<param name="File" value="JDBCExceptionReporter.log"/>
<param name="MaxFileSize" value="50000KB"/>
<param name="MaxBackupIndex" value="5"/>
<param name="BufferedIO" value="false"/>
<param name="ImmediateFlush" value="true"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d, %-5p, %X{ORG_NAME}, %X{USER_NAME}, %c - %m%n"/>
<!-- Use pattern below if it is required to view the log files -->
<!-- using LogFactor5-->
<!--<param name="ConversionPattern" value="[slf5s.start] %d[slf5s.DATE]
%-5p[slf5s.PRIORITY] %X{ORG_NAME} %X{USER_NAME}
[slf5s.NDC] %c[slf5s.CATEGORY] - %m[slf5s.MESSAGE] %n"-->
</layout>
</appender>
Finally, I added those loggers just before the root element :
<logger name="org.hibernate" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.type" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.tool.hbm2ddl" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.pretty" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.cache" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.transaction" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.jdbc" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.hql.ast.AST" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.secure" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
<logger name="org.hibernate.SQL" additivity="false">
<level value="ALL"/>
<appender-ref ref="JDBCExceptionReporter"/>
</logger>
This configuration didn’t work and the two lines are always logged in the SystemOut.log and not in my JDBCExceptionReporter.log.
does anyone have the answer to my problem ?
thank you for your help.
Hibernate does not use Log4J directly. This is why your messages are falling into WebSphere SystemOut.log file.
Up to version 3.2, hibernate used Jakarta Commons Logging as a logging facade. From version 3.3 and above, it switched to SLF4J (Simple Logging Facade for Java). As jakarta commons logging (JCL), SLF4J is just a facade, often binding to other Logging Frameworks, like Java Logging or, in this case, Log4J itself.
I understand your application already uses Log4J. I’m also assuming you’re using Hibernate 3.3 or a newer version.
The first thing is to add SLF4J support to your project. You do that by adding these dependencies (with Ivy, Maven or however you want):
slf4j-api.jar (Core SLF4J packages)
slf4j-log4j12.jar (Binds SLF4J to Log4J)
This way, when Hibernate logs some message, SLF4J will capture it and route it to Log4J.
Now, when it comes up to your own app code, you have two approaches.
1: Keep your classes directly interacting to Log4J classes (namely Logger and LoggerFactory)
This way, you keep your classes directly referencing Log4J Logger, like this:
So, in short, Hibernate will use SLF4J -> Log4J and you will use directly Log4J
2: The second approach is to have your code use SLF4J as well. This isn’t so big a change, as you’ll probably have to change just one line of code in each of your classes that produces log messages:
If you are using an older version of Hibernate (3.2 or older), you’ll have to trick It not to use Jakarta Commons Logging. First, you’ll have to purge commons-logging JAR files from your dependencies (either manually or with an exclusion, if you use any dependency manager). Then you’ll have to add an SLF4J port of commons-logging to your classpath:
add jcl-over-slf4j-x.y.z.jar (x.y.z being its version. I use jcl-over-slf4j-1.6.1.jar, for example).
This jar has the exact classes and packages of old commons-logging.jar, thus effectively tricking all commons-logging dependent applications to log to SLF4J in fact.