Monday, September 19, 2016

Hibernate : log4j.xml logging category and binding parameters




down voteaccepted
Here's the list of logger categories:
Category                    Function

org.hibernate.SQL           Log all SQL DML statements as they are executed
org.hibernate.type          Log all JDBC parameters
org.hibernate.tool.hbm2ddl  Log all SQL DDL statements as they are executed
org.hibernate.pretty        Log the state of all entities (max 20 entities) associated with the session at flush time
org.hibernate.cache         Log all second-level cache activity
org.hibernate.transaction   Log transaction related activity
org.hibernate.jdbc          Log all JDBC resource acquisition
org.hibernate.hql.ast.AST   Log HQL and SQL ASTs during query parsing
org.hibernate.secure        Log all JAAS authorization requests
org.hibernate               Log everything (a lot of information, but very useful for troubleshooting) 
Formatted for pasting into a log4j XML configuration file:
<!-- Log all SQL DML statements as they are executed -->
<Logger name="org.hibernate.SQL" level="debug" />
<!-- Log all JDBC parameters -->
<Logger name="org.hibernate.type" level="debug" />
<!-- Log all SQL DDL statements as they are executed -->
<Logger name="org.hibernate.tool.hbm2ddl" level="debug" />
<!-- Log the state of all entities (max 20 entities) associated with the session at flush time -->
<Logger name="org.hibernate.pretty" level="debug" />
<!-- Log all second-level cache activity -->
<Logger name="org.hibernate.cache" level="debug" />
<!-- Log transaction related activity -->
<Logger name="org.hibernate.transaction" level="debug" />
<!-- Log all JDBC resource acquisition -->
<Logger name="org.hibernate.jdbc" level="debug" />
<!-- Log HQL and SQL ASTs during query parsing -->
<Logger name="org.hibernate.hql.ast.AST" level="debug" />
<!-- Log all JAAS authorization requests -->
<Logger name="org.hibernate.secure" level="debug" />
<!-- Log everything (a lot of information, but very useful for troubleshooting) -->
<Logger name="org.hibernate" level="debug" />
NB: Most of the loggers use the DEBUG level, however org.hibernate.type uses TRACE. In previous versions of Hibernate org.hibernate.type also used DEBUG, but as of Hibernate 3 you must set the level to TRACE (or ALL) in order to see the JDBC parameter binding logging.
And a category is specified as such:
<logger name="org.hibernate">
    <level value="ALL" />
    <appender-ref ref="FILE"/>
</logger>
It must be placed before the root element.

Monday, September 5, 2016

Hibernate 4 - publish changes / updates to the schema with entities in Spring JavaConfig

package com.mycompany.domain.test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.source.MetadataImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;

public class JpaSchemaExport {
   
   private static final Logger LOGGER = Logger.getLogger(JpaSchemaExport.class);
     
   public static void main(String[] args) throws MappingException, IOException, ClassNotFoundException {
      BasicConfigurator.configure();
      Configuration c = new Configuration();
      Class[] clzzs = getClasses("com.mycompany.domain.entity");
      for (int i = 0; i < clzzs.length; i++) {
         c.addAnnotatedClass(clzzs[i]);
      }
      Properties hibernateProperties = new Properties();
      hibernateProperties.put("hibernate.connection.driver_class","oracle.jdbc.OracleDriver");
      hibernateProperties.put("hibernate.connection.url","jdbc:oracle:thin:@");
      hibernateProperties.put("hibernate.connection.username","scott");
      hibernateProperties.put("hibernate.connection.password","secret99");
      hibernateProperties.put("hibernate.show_sql", true);
      hibernateProperties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
      hibernateProperties.put("hibernate.format_sql", true);
      hibernateProperties.put("connection.pool_size", 3);
      hibernateProperties.put("current_session_context_class", "thread");
      hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
      c.addProperties(hibernateProperties);
      
      StandardServiceRegistryBuilder registry = new StandardServiceRegistryBuilder();
      registry.applySettings(c.getProperties());

      ServiceRegistry serviceRegistry = registry.build();
      MetadataImplementor metadata = (MetadataImplementor) new MetadataSources(serviceRegistry).buildMetadata();

      SchemaUpdate schemaExport = new SchemaUpdate(serviceRegistry, c);

      // use this line when exporting the whole DDL 
      //SchemaExport schemaExport = new SchemaExport(serviceRegistry,c);
      File f = new File("export.sql");  
      schemaExport.setOutputFile(f.getAbsolutePath());
      System.err.println(f.getAbsolutePath());
      schemaExport.execute(true, false);
      

      if (schemaExport.getExceptions().size() > 0) {
         Iterator iterator = schemaExport.getExceptions().iterator();
         int cnt = 1;
         LOGGER.warn(schemaExport.getExceptions().size() + " errors occurred while performing .");
         while (iterator.hasNext()) {
             LOGGER.error("Error #" + cnt + ": " + iterator.next().toString());
         }

     }
      
      ( (StandardServiceRegistryImpl) serviceRegistry ).destroy();
  }
  
  /**
   * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
   *
   * @param packageName The base package
   * @return The classes
   * @throws ClassNotFoundException
   * @throws IOException
   */
  private static Class[] getClasses(String packageName)
          throws ClassNotFoundException, IOException {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      assert classLoader != null;
      String path = packageName.replace('.', '/');
      Enumeration resources = classLoader.getResources(path);
      List dirs = new ArrayList();
      while (resources.hasMoreElements()) {
          URL resource = resources.nextElement();
          dirs.add(new File(resource.getFile()));
      }
      ArrayList classes = new ArrayList();
      for (File directory : dirs) {
          classes.addAll(findClasses(directory, packageName));
      }
      return classes.toArray(new Class[classes.size()]);
  }

  /**
   * Recursive method used to find all classes in a given directory and subdirs.
   *
   * @param directory   The base directory
   * @param packageName The package name for classes found inside the base directory
   * @return The classes
   * @throws ClassNotFoundException
   */
  private static List findClasses(File directory, String packageName) throws ClassNotFoundException {
      List classes = new ArrayList();
      if (!directory.exists()) {
          return classes;
      }
      File[] files = directory.listFiles();
      for (File file : files) {
          if (file.isDirectory()) {
              assert !file.getName().contains(".");
              classes.addAll(findClasses(file, packageName + "." + file.getName()));
          } else if (file.getName().endsWith(".class")) {
              classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
          }
      }
      return classes;
  }  
}