Hibernate可以与任何一种Java应用的运行环境集成。Java应用的运行环境可分为两种: 
受管理环境(Managed environment):由容器负责管理各种共享资源(线程池和数据库连接池等),支持CMT(Container Managered Transaction,完全由容器管理事务)事务模式等。 
不受管理环境(Non-managed environment):由应用本身负责管理数据库连接、定义事务边界及管理安全,独立的桌面应用或命令行应用都运行在不受管理环境中。Servlet容器会负责管理线程池,但Servlet容器不支持CMT事务模式,因此它提供的仍然是不受管理的运行环境。 

数据库连接池的基本实现原理是:事先建立一定数量的数据库连接,这些连接存放在连接池中,当java应用执行一个数据库事务时,只需从连接池中取出空闲状态的数据库连接;当java应用执行完事务,再将数据库连接放回连接池。 

对于使用Hibernate的Java应用,构造及访问连接池的任务通常由Hibernate完成。 
在受管理环境中,容器负责构造连接池的实例,Java应用直接访问容器提供的连接池实例。不同的连接池有不同的API,若Java应用直接访问连接池的API,会削弱Java应用与连接池之间的独立性。为提高Java应用与连接池之间的独立性,SUN公司指定了标准的javax.sql.DataSource接口,用于封装各种不同的连接池实现。对于每一种实现javax.sql.DataSource接口的连接池,都会提供负责构造DataSource实例的工厂类。在受管理环境中,容器通过这个工厂类构造出DataSource实例,然后把它发布为JNDI(Java Naming and Directory Interface)资源,允许java应用通过JNDI API来访问它。 
可以简单地把JNDI理解为一种将对象和名字绑定的技术,对象工厂负责生产出对象,这些对象都和唯一的JNDI名字绑定,外部程序通过JNDI名字获得某个对象的引用。 

Hibernate有3种方式获得数据库连接池:使用默认的数据库连接池、使用配置文件指定的数据库连接池、在受管理环境中,从容其中获得标准的数据源。 
Hibernate把不同来源的连接池抽象为org.hibernate.connection.ConnectionProvider接口,Hibernate提供了以下内置的ConnectionProvoder实现类。 
DriverManagerConnectionProvider:代表由Hibernate提供的默认的数据库连接池 C3P0Connection:代表C3P0连接池 
ProxoolConnectionProvider:代表Proxool连接池 
DataSourceConnectionProvider:代表在受管理环境中由容器提供的数据源 

Hibernate还允许用户扩展ConnectionProvider接口,创建客户化ConnectionProvider实现类。在Hibernate配置文件中,hibernate.connection.provider_class属性用来指定ConnectionProvider实现类。Hibernate的ConnectionProviderFactory工厂类根据provider_class属性来构造相应的ConnectionProvider实例。若用户使用的是Hibernate的内置ConnectionProvider实现类,也可不设置provider_class属性。 

使用C3P0连接池的hibernate.properties文件 
hibernate.dialect=org.hibernate.dialect.MySQLDialect 
hibernate.connection.driver_class=com.mysql.jdbc.Driver 
hibernate.connection.url=jdbc:mysql://localhost:3306/DBName 
hibernate.connection.username=forever 
hibernate.connection.password=forever 
hibernate.show_sql=true 
hibernate.c3p0.min_size=5     //在连接池中可用的数据库的最少数目 
hibernate.c3p0.max_size=20    //在连接池中所有数据库连接的最大数目 
hibernate.c3p0.timeout=300    //设定数据库连接的过期时间,以秒为单位 
hibernate.c3p0.max_statements=50  //可以被缓存的PreparedStatement实例的最大数目 
hibernate.c3p0.idle_test_period=300  //在使数据库连接自动生效之前处于空闲状态的时间,以秒为单位 

在受管理环境中,容器负责构造数据源,即javax.sql.DataSource的实例,然后把它发布为JNDI资源,Hibernate的DataSourceConnectionProvider类充当这个数据源的代理。在不受管理环境中,有些Servlet容器,如Tomcat,也可负责构造数据源,并能把它发布为JNDI资源。 

以Tomcat为例,为了使Hibernate从容器中获得数据源,需要分别设置Tomcat容器和Hibernate: 
在Tomcat容器中配置数据源;在Hibernate的配置文件中指定使用个容器中的数据源。 
在Tomcat容器中配置数据源: 
在Tomcat的配置问价server.xml中,<Resource>元素用来匹配JNDI资源,Tomcat允许把数据源也发布为JNDI资源 
<Resource 
    name="jdbc/SAMPLEDB"  //指定Resource的JNDI名字 
    auth="Container"  //指定Resoucre的Manager:Container(容器)和Application(Web应用) 
    type="javax.sql.DataSource" //指定Resource所述的Java类名 
    maxActive="100" //指定数据库连接池中处于活动状态的数据库连接的最大数目 
    maxIdle="30"  //指定数据库连接池中处于空闲状态的数据库连接的最大数目 
    maxWait="10000" //指定数据库连接池中的数据库链接处于空闲状态的最长时间 
    username="root"  
    password="tiger" 
    driverClassName="com.muysql.jdbc.Driver" 
    url="jdbc:mysql://localhost:3306/SAMPLEDB?autoReconnect=true"     
/> 
在Hibernate配置文件中指定使用容器中的数据源 
在Hibernate的配置文件中,hibernate.connection.datasoure属性用于指定容器中的数据源。 
hibernate.dialect=org.hibernate.dialect.MySQLDialect 
hibernate.connection.dtasource=java:comp/env/jdbc/SAMPLEDB 
hibernate.show_sql=true 

当Java应用通过Hibernate访问数据库时,先调用SessionFactory的openSession()方法获得一个Session实例,然后通过Session实例执行具体的数据库操作。对于每一个Session实例,Hibernate都会为它分配数据库连接。在默认的情况下,Hibernate从数据库连接池中获得可用的数据库连接。此外,Hibernate还允许由应用程序为ession指定数据库连接。SessionFactory的openSession()方法有以下几种重载方式: 
openSession():由Hibernate从数据库连接池中获得可用的数据库连接 
openSession(Connection connection):由应用程序提供数据库连接 

在Java应用中,按照声明事务边界的接口划分,事务可分为两类: 
JDBC事务:依赖于JDBC API来声明事务边界,适用于任何Java环境 
JTA事务,依赖于JTA来声明事务边界,适用于基于J2EE的受管理环境,以及支持JTA的不受管理环境。 
JTA(Java Transaction API)是SUN公司为就JavaEE的受管理环境制定的标准事务API。此外,有些JTA实现可以脱离容器独立运行,因此在不受管理环境中,Java应用过可访问基于这种实现的JTA。JTA支持分布式的事务及扩数据库平台的事务。JTA中的两个核心接口为: 
TransactionManager:事务管理器,参与管理事务的生命周期 
UserTransaction:Java应用通过这个接口来声明事务边界 
在受管理环境中,JTA事务分为CMT(Container Managered Transaction,完全由容器管理事务)和BMT(Bean Managered Transaction,由Bean来管理自己的事务)两种模式。在CMT事务模式下,应用不必再程序代码中声明事务边界,而只需在部署文件中配置事务,然后由容器通过TransactionManager来管理事务。在BMT事务模式下,应用在程序代码中通过UserTransaction接口来声明事务边界。 

对于使用Hibernate的Java应用,Java应用声明事务有两种方式: 
直接通过JTA API来声明JTA事务。 
通过Hibernate API来声明事务。 

Hibernate把不同类型的事务抽象为org.hibenate.Transaction接口,并提供了两个内置的实现类:JDBCTransaction(代表JDBC事务)、JTATransaction(代表JTA事务)。 
Hibernate通过以下事务工厂类来狗仔JDBC或JTA事务实例: 
JDBCTransactionFactory:负责构造JDBCTransaction实例 
JTATransactionFactory:负责构造JTATransaction实例 
hibernate.dialect=org.hibernate.dialect.MySQLDialect 
hibernate.connection.datasource=java:comp/env/jdbc/SAMPLEDB 
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory 
//指定TransactionManagerLookUp接口的实现类,负责定位容器中JTATransactionManager 
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JBossTransactionManagerLookip 
hibernate.show_sql=true 
只有当毒药使Hibernate的第二级缓存,或使用了hilo标识符生成策略,或由容器来管理事务时,才必须设置manager_lookup_class属性,在其他情况下,可以不设置manager_lookup_class属性。 

若应用程序仅在不受管理环境中运行,可以采用默认的JDBC事务,应用程序通过Hibernate API来声明事务边界,在配置文件中采用默认的JDBCTransactionFactory事务工厂。若应用程序仅在受管理环境中运行,应该优先考虑采用JTA事务,应用程序通过JTA API来声明事务边界,在配置文件中配置JTATransactionFactory事务工厂。 

如何配置事务? 
为了保证应用程序代码的独立性,以及在各种运行环境下具有相同的运行时行为,优先考虑在程序中通过JTA API来声明事务。应用发布者负责配置不受管理或受管理环境中JTA实现的提供者。此外,事务的集成及资源的管理也由应用发布者,而不是应用程序来负责。在Hibernate配置文件中应该配置JTATransactionFactory事务工厂,此外,还要配置相应的TransactionManagerLookup。 
其次,对于EJB组件,可以采用CMT事务模式。 
最后,在万不得已的情况下,如必须保证声明事务的程序代码的兼容性,并且在不受管理环境下不支持JTA,可以考虑在程序中通过Hibernate API来声明事务。此时Hibernate API根据在各个环境下配置的特定事务工厂(JDBCTransactionFactory或JTATransactionFactory),自动切换到JDBC事务或JTA事务。 

在不同的运行环境中,SessionFactory有不同的存取方案: 
创建一个实用类:HibernateUtil,在这个类中定义static类型的SessionFactory变量,以及public static 类型的getSessionFactory()方法 
在Servlet容器中,把SessionFactory实例存放在javax.servlet.ServletContext中,即JavaWeb应用范围内。 
在基于JavaEE的受管理环境中,把SessionFactory发布为JNDI资源。 

在Hibernate的配置文件中,hibernate.session_factory_name属性指定SessionFactory的JNDI名字,若受管理环境中设置了这个属性,Hibernate就会把SessionFactory发布为JNDI资源 
hibernate.dialect=org.hibernate.dialect.MySQLDialect 
hibernate.connection.datasource=java:copm/env/jdbc/SAMPLEDB 
hibernate.transaction.factory_Class=org.hibernate.transaction.JTATransactionFactory 
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JTATransactionManagerLookup 
hibernate.session_factory_name=java:hibernate/HibernateFactory 
hibernate.show_sql=true 
Context ctx = new InitialContext(); 
String jndiName="java:hibernate/HibernateFactory"; 
SessionFactory sessionFactory = (SessionFactory)ctx.lookup(jndiName); 
Session session = sessionFactory.openSession(); 
... 

Hibernate采用SLF4J(Simple Logging Facade for Java)日志工具来记录各种各样的系统事件。SLF4J把日志由低到高分为5个级别:DEBUG、INFO、WARN、ERROR和FATAL。 
SLF4J对目前常见的一些日志工具提供了适配器,对这些日志工具提供了服务进行了抽象,为客户程序提供了统一的输出日志的API: 
NOP:什么也不做,不输出任何日志 
Simple:SLF4J自带的简单的日志工具实现,通过System.err来输出日志,仅输出INFO级别或更高级别的日志 
Log4J:允许指定日志信息输出的目的地,还可以控制每一条日志的输出格式,此外,通过定义日志信息的级别,Log4J能非常细致地控制日志的输出与否。可以通过log4j.properties配置 
JDK1.4Log:JDK1.4及以上版本中自带的日志工具 
JCL(Jakarta Commons Logging):提供了通用的输出日志的API 

log4j.properties 
#指定根日志器的输出目的地,输出日志级别 
log4j.rotLogger=WARM, A1,A2 

#A1为控制台 
log4j.appender.A1=org.apache.log4j.ConsoleAppender 

#指定向A1控制台输出的日志的格式 
log4j.appender.A1.layout=org.apache.log4j.PatternLayout 
log4j.appender.A1.layout.ConversionPattern=%p [%t] %c{2} {%m:%L} - %m%n 

#A2为C:/log.txt文件 
log4j.appender.A2=org.apache.log4j.FileAppender 
log4j.appender.A2.File=C:/log.txt 

#指定向A2控制台输出的日志的格式 
log4j.appender.A2.layout=org.apache.log4j.PatternLayout 
log4j.appender.A2.layout.ConversionPattern=%5r %-5p [%t] $c{2} -%m%n 

log4j.logger.org.hibernate=INFO 
log4j.logger.org.hibernate.hql.ast.AST=DEBUG 
log4j.logger.org.hibernate.SQL=DEBUG 
log4j.logger.org.hibernate.tool.hbm2ddl=DEBUG 
log4j.logger.org.hibernate.hql=DEBUG