Hibernate Log4j日志记录

时间:2020-02-23 14:41:24  来源:igfitidea点击:

欢迎使用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。