Hibernate Log4j日志记录
欢迎使用Hibernate Log4j日志记录示例。
在较早的休眠版本中,Hibernate 4使用JBoss日志记录而不是slf4j。
今天,我们将研究如何在休眠应用程序中配置log4j。
Hibernate Log4j日志记录
在Eclipse或者您最喜欢的IDE中创建一个maven项目,最终项目结构如下图所示。
让我们逐一研究每个组件。
Hibernate Log4j Maven依赖关系
我们的项目中需要hibernate-core,mysql驱动程序和log4j依赖项,最终的pom.xml文件如下所示。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.theitroad.hibernate</groupId> <artifactId>HibernateLog4JExample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.5.Final</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.5</version> </dependency> </dependencies> </project>
Log4j配置文件
我正在使用基于XML的log4j配置,我们也可以使用基于属性文件的配置。
log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="https://jakarta.apache.org/log4j/" debug="false"> <!-- A time/date based rolling appender --> <appender name="FILE" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="logs/system.log" <param name="Append" value="true" <param name="ImmediateFlush" value="true" <param name="MaxFileSize" value="200MB" <param name="MaxBackupIndex" value="100" <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" </layout> </appender> <appender name="theitroad-hibernate" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="logs/project.log" <param name="Append" value="true" <param name="ImmediateFlush" value="true" <param name="MaxFileSize" value="200MB" <param name="MaxBackupIndex" value="50" <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %d{Z} [%t] %-5p (%F:%L) - %m%n" </layout> </appender> <logger name="com.theitroad.hibernate" additivity="false"> <level value="DEBUG" <appender-ref ref="theitroad-hibernate" </logger> <logger name="org.hibernate" additivity="false"> <level value="INFO" <appender-ref ref="FILE" </logger> <root> <priority value="INFO"></priority> <appender-ref ref="FILE" </root> </log4j:configuration>
该文件需要放在根文件夹中,以便我们的主类可以访问它。
注意log4j日志文件的位置,我们的应用程序生成的日志将进入project.log,而休眠日志将进入system.log文件。
休眠配置文件
我们的休眠配置xml如下所示。
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "classpath://org/hibernate/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.password">hyman123</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property> <property name="hibernate.connection.username">hyman</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.show_sql">true</property> <mapping class="com.theitroad.hibernate.model.Employee" <mapping class="com.theitroad.hibernate.model.Address" </session-factory> </hibernate-configuration>
Hibernate SessionFactory实用程序类
package com.theitroad.hibernate.util; import org.apache.log4j.Logger; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class HibernateUtil { private static SessionFactory sessionFactory; private static Logger logger = Logger.getLogger(HibernateUtil.class); private static SessionFactory buildSessionFactory() { try { //Create the SessionFactory from hibernate.cfg.xml Configuration configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); logger.info("Hibernate Configuration loaded"); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); logger.info("Hibernate serviceRegistry created"); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); return sessionFactory; } catch (Throwable ex) { logger.error("Initial SessionFactory creation failed." + ex); ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { if(sessionFactory == null) sessionFactory = buildSessionFactory(); return sessionFactory; } }
注意,我正在使用log4j Logger进行日志记录,因为此类是我们应用程序的一部分,因此日志应放入project.log文件中。
模型类
我们有两个模型类-雇员和地址。
我正在使用与HQL示例中相同的数据库设置,因此您可以检查该教程以研究数据库设置和模型类。
这两个类都是简单的Java Bean,具有基于休眠注释的映射。
Hibernate Log4j日志记录测试类
我们的主要类如下所示。
package com.theitroad.hibernate.main; import java.util.List; import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.theitroad.hibernate.model.Employee; import com.theitroad.hibernate.util.HibernateUtil; public class HibernateLog4jExample { static{ System.out.println("Before log4j configuration"); DOMConfigurator.configure("log4j.xml"); System.out.println("After log4j configuration"); } private static Logger logger = Logger.getLogger(HibernateLog4jExample.class); @SuppressWarnings("unchecked") public static void main(String[] args) { //Prep work SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.getCurrentSession(); //Get All Employees Transaction tx = session.beginTransaction(); Query query = session.createQuery("from Employee"); List<Employee> empList = query.list(); for(Employee emp : empList){ logger.info("List of Employees::"+emp.getId()+","+emp.getAddress().getCity()); } tx.commit(); sessionFactory.close(); logger.info("DONE"); } }
请注意,我们不需要对插件log4j日志进行任何操作。
显然,在使用它之前,我们需要先对其进行配置,这就是为什么我在开始使用它之前要使用静态块来确保已配置log4j的原因。
我使用的是org.apache.log4j.xml.DOMConfigurator,因为我们的log4j配置基于XML,如果您具有基于属性文件的配置,则应使用org.apache.log4j.PropertyConfigurator类。
现在,当我们执行上述程序时,将在log4j文件中获取以下数据。
project.log
2014-06-05 20:00:11,868 -0700 [main] INFO (HibernateUtil.java:20) - Hibernate Configuration loaded 2014-06-05 20:00:11,936 -0700 [main] INFO (HibernateUtil.java:23) - Hibernate serviceRegistry created 2014-06-05 20:00:12,698 -0700 [main] INFO (HibernateLog4jExample.java:37) - List of Employees::1,San Jose 2014-06-05 20:00:12,698 -0700 [main] INFO (HibernateLog4jExample.java:37) - List of Employees::2,Santa Clara 2014-06-05 20:00:12,698 -0700 [main] INFO (HibernateLog4jExample.java:37) - List of Employees::3,Bangalore 2014-06-05 20:00:12,698 -0700 [main] INFO (HibernateLog4jExample.java:37) - List of Employees::4,New Delhi 2014-06-05 20:00:12,712 -0700 [main] INFO (HibernateLog4jExample.java:42) - DONE
注意,上面的日志文件仅包含由程序生成的条目,这样我们就可以将应用程序日志与休眠日志分开。
system.log
2014-06-05 22:49:58,415 -0700 [main] INFO (JavaReflectionManager.java:66) - HCANN000001: Hibernate Commons Annotations {4.0.4.Final} 2014-06-05 22:49:58,423 -0700 [main] INFO (Version.java:54) - HHH000412: Hibernate Core {4.3.5.Final} 2014-06-05 22:49:58,426 -0700 [main] INFO (Environment.java:239) - HHH000206: hibernate.properties not found 2014-06-05 22:49:58,427 -0700 [main] INFO (Environment.java:346) - HHH000021: Bytecode provider name : javassist 2014-06-05 22:49:58,446 -0700 [main] INFO (Configuration.java:2073) - HHH000043: Configuring from resource: hibernate.cfg.xml 2014-06-05 22:49:58,447 -0700 [main] INFO (Configuration.java:2092) - HHH000040: Configuration resource: hibernate.cfg.xml 2014-06-05 22:49:58,491 -0700 [main] INFO (Configuration.java:2214) - HHH000041: Configured SessionFactory: null 2014-06-05 22:49:58,557 -0700 [main] WARN (DriverManagerConnectionProviderImpl.java:93) - HHH000402: Using Hibernate built-in connection pool (not for production use!) 2014-06-05 22:49:58,560 -0700 [main] INFO (DriverManagerConnectionProviderImpl.java:166) - HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/TestDB] 2014-06-05 22:49:58,561 -0700 [main] INFO (DriverManagerConnectionProviderImpl.java:175) - HHH000046: Connection properties: {user=hyman, password=} 2014-06-05 22:49:58,561 -0700 [main] INFO (DriverManagerConnectionProviderImpl.java:180) - HHH000006: Autocommit mode: false 2014-06-05 22:49:58,562 -0700 [main] INFO (DriverManagerConnectionProviderImpl.java:102) - HHH000115: Hibernate connection pool size: 20 (min=1) 2014-06-05 22:49:58,699 -0700 [main] INFO (Dialect.java:145) - HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect 2014-06-05 22:49:58,706 -0700 [main] INFO (LobCreatorBuilder.java:97) - HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4 2014-06-05 22:49:58,828 -0700 [main] INFO (TransactionFactoryInitiator.java:62) - HHH000399: Using default transaction strategy (direct JDBC transactions) 2014-06-05 22:49:58,832 -0700 [main] INFO (ASTQueryTranslatorFactory.java:47) - HHH000397: Using ASTQueryTranslatorFactory 2014-06-05 22:49:59,207 -0700 [main] INFO (DriverManagerConnectionProviderImpl.java:281) - HHH000030: Cleaning up connection pool [jdbc:mysql://localhost/TestDB]
由于我们的休眠日志级别设置为INFO模式,因此日志很少。
如果您将其更改为调试,那么即使这个简单的程序也会生成1400多行日志。
有时,分析这些日志对于了解休眠在内部的工作方式以及调试与休眠有关的问题非常重要。
此外,我们在控制台中生成了以下日志。
Before log4j configuration After log4j configuration Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
注意,Hibernate正在将SQL查询打印到控制台日志,这是从org.hibernate.engine.jdbc.spi.SqlStatementLogger类class logStatement方法中发生的,代码片段为:
if (this.logToStdout) System.out.println("Hibernate: " + statement);
这由hibernate.cfg.xml文件中的hibernate.show_sql属性控制。
实际上,如果您正在使用log4j,则应将其关闭,因为如果将日志记录级别设置为DEBUG模式,它们也将成为日志文件的一部分。
将其保存在日志文件中比在控制台上打印更有意义。
这就是休眠log4j记录示例的全部内容,如您所见,它非常容易插入,而我们所需要做的就是正确配置log4j。