hibernate的配置文件及连接池

时间:2022-09-20 07:47:30

hibernate可以与任何一种Java应用的运行环境集成。Java应用的运行环境可分为两种:
1,受管理环境Managed environment,由容器负责管理各种共享资源,如线程池和数据库连接池,以及管理事务和安全。一些J2EE应用服务器,如JBoss,WebLogic和WebSphere提供了符合J2EE规范的受管理环境。
2,不受管理环境Non-managed environment,由应用本身负责管理数据库连接,定义事务边界以及管理安全。独立的桌面应用或命令行应用都运行在不受管理环境中,servlet容器会负责管理线程池,有些servlet容器,如tomcat,还会管理数据库连接池,但是servlet容器不会管理事务,因此它提供的仍然是不受管理的运行环境。
hibernate允许Java应用在不同的环境中移植。移植只需要修改hibernate的配置文件,而不需要修改或只需要修改少量的Java源代码。

所有的Java应用最终都必须通过JDBC API来访问数据库。
在不受管理的环境中,Java应用自身负责构造特定的连接池实例,然后访问这个连接池的API,从连接池中获得数据库连接。
在受管理的环境中,容器负责构造连接池的实例,Java应用直接访问容器提供的连接池实例。
JNDI技术可以简单的理解为一种将对象/服务和名字绑定的技术;它在受管理的环境中得到了广泛的运用。

hibernate把不同来源的连接池抽象为net.sf.hibernate.connection.ConnectionProvider接口,并提供了以下内置的ConnectionProvider实现类。、
DriverManagerConnectionProvider:代表hibernate提供的默认的数据库连接池。
DataSourceConnectionProvider:代表在受管理环境中由容器提供的数据源。
DBCPConnectionProvider:代表DBCP连接池。
C3P0ConnectionProvider:代表C3P0连接池。
ProxoolConnectionProvider:代表Proxool连接池。
连接池用户也可以扩展,写自己的连接池。这里不写了,可以用百度一下。

hibernate提供了默认的连接池实现,它的实现类为DriverManagerConnectionProvider,如果在hibernate的配置文件中没有明确配置任何连接池,hibernate就会使用这个默认的连接池。在生产环境中不要使用这个连接池,因为它缺乏响应大批量并发请求以及容错的能力。
不管是在受管理环境中,还是在不受管理环境中,都可以在配置文件中显式配置特定数据库连接池。hibernate会负责构造这种连接池的实例,然后通过它获得数据库连接。
hibernate目前支持的第三方连接池产品包括:C3P0,Proxool,DBCP,hibernate开发组织优先推荐的是C3P0和Proxool。C3P0配置的例子如下:
hibernate.c3p0.min_size=5//在连接池中可用的数据库连接的最少数目
hibernate.c3p0.max_size=20//在连接池中可用的数据库连接的最多数目
hibernate.c3p0.timeout=300//设定数据库连接的过期时间,以秒为单位。如果连接池中的某个数据库连接处于空闲状态的时间超过了指定的时间,就会从连接池中清除。
hibernate.c3p0.max_statements=50//可以被缓存的PreparedStatement实例的最大数目。缓存适量的PreparedStatement实例,能够大大提高hibernate的性能。
hibernate.c3p0.idle_test_period=3000//在使数据库连接自动生效之前处于空闲状态的时间,以秒为单位。

不同的连接池有不同的配置选项。

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

以tomcat为例,为了使hibernate从容器中获得数据源,需要分别配置tomcat容器和hibernate:
1,在tomcat容器中配置数据源;2,在hibernate的配置文件中指定使用容器中的数据源。

tomcat的配置文件server.xml中,<Resource>元素用来配置JNDI资源,它允许把数据源也发布为JNDI资源,如:
<Resource name="jdbc/SAMPLEDB" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/SAMPLEDB">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>username</name>
<value>root</value>
</parameter>
<parameter>
<name>password</name>
<value>1234</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:mysql://loaclhost:3306/SAMPLEDB?autoReconnection=true</value>
</parameter>
</ResourceParams>
以上代码设置了<Resource>和<ResourceParams>元素。
<Resource>的属性值描述如下:
name:指定resource的JNDI名字。
auth:指定管理resource的manager,它有两个可选的值:Container和Application;分别表示由容器和由WEB应用程序来创建和管理resource。
type:指定resource所属的Java类名。
在<ResourceParams>元素中指定了配置数据源的各种参数:
factory:生成DataSource的factory类名。
maxActive:数据库连接池中处于活动状态的数据库连接的最大数目,取值为0,表示不受限制。
maxIdle:数据库连接池中处于空闲状态的数据库连接的最大数目,取值为0,表示不受限制。
maxWait:数据库连接池中的数据库连接处于空闲状态的时长时间,以毫秒为单位,超过这一时间,将会抛出异常,取值为-1,表示可以无限制等待。
username:数据库用户名
password:数据库密码
driverClassName:JDBC驱动程序
url:数据库连接URL。

hibernate的配置文件中配置如下:
hibernate.connection.datasource=java:comp/env/jdbc/SAMPLEDB
指定数据源时,必须提供完整的JNDI名字。因为使用了数据源,所以在hibernate配置文件中无须再指定以下参数:hibernate.connection.url,hibernate.connection.username,hibernate.connection.password。

Java应用本身提供数据库连接这里不介绍了,如果session使用的是java应用提供的Connection实例,那么hibernate的二级缓存就会失效。


在Java应用中,按照声明事务边界的接口划分,事务可分为两类:
1,JDBC事务,通过JDBC API来声明事务边界,适用于任何Java运行环境。
2,JTA事务,通过JTA来声明事务边界,适用于基于J2EE的受管理环境。
JTA(Java Transaction API)是SUN公司为基于J2EE的受管理环境制定的标准事务API,JTA支持分布式的事务以及跨数据库平台的事务,JTA中的两个核心接口如下:
1,TransactionManager:在CMT环境中,容器通过这个接口来声明事务边界。CMT(Container-managered Transaction)是指由容器来负责管理事务,在Java应用中不必编写声明事务边界的程序代码。
2,UserTransaction:Java应用通过这个接口来声明事务边界。
对于使用了hibernate的Java应用,Java应用不必直接访问JDBC API或JTA,而是由hibernate来声明JDBC事务或JTA事务。不管hibernate使用的是哪种事务,对Java应用是透明的。在hibernate的配置文件中,hibernate.transaction.factory_class属性用来指定事务工厂类,它的默认值为net.sf.hibernate.transaction.JDBCTransactionFactory。下面配置了JTA事务如:
hibernate.transaction.factory_class=net.sf.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class=net.sf.hibernate.transaction.JBossTransactionManagerLookup

hibernate.transaction.manager_lookup_class这个属性用于指定TransactionManagerLookup接口的实现类,这个接口负责定位容器中的JTA TransactionManager。hibernate为许多J2EE应用服务器提供了实现类,如JBoss的实现类为JBossTransactionManagerLookup。只有当需要使用二级缓存并且由容器管理事务时,才必须设置manager_lookup_class属性,其它情况下可以不必设置。
当使用JTA事务时,还可以显式指定JTA UserTransaction的JNDI名字,UserTransaction在容器中被发布为JNDI资源,下面是例子:
hibernate.transaction.factory_class=net.sf.hibernate.transaction.JTATransactionFactory
hibernate.jta.UserTransaction=java:comp/UserTransaction

应用程序中的SessionFactory的存取方案:
1,创建一个实用类HibernateUtil,在这个类中定义static类型的SessionFactory变量,以及public static类型的getSessionFactory()方法。
2,在Servlet容器中,把SessionFactory实例存放在ServletContext中。
3,在基于J2EE的受管理环境中,把SessionFactory发布为JNDI资源。在hibernate配置文件中,hibernate.session_factory_name属性指定SessionFactory的JNDI名字,如果在受管理环境中设置了这个属性,hibernate就会把SessionFactory发布为JNDI资源。如:
配置文件中设置:hibernate.session_factory_name=java:hibernate/HibernateFactory
Java应用通过JNDI来访问:
Context context = new InitialContext();
String jndiName = "java:hibernate/HibernateFactory"
SessionFactory sessionFactory = (SessionFactory)context.lookup(jndiName);
Session session = sessionFactory.openSession();
以上程序代码只能在J2EE应用服务器内运行,不能在J2EE应用服务器外运行,因为SessionFactory不支持RMI(remote method invoke远程方法调用)。

如果hibernate配置文件格式为.properties,那么必须以编程方式声明需要加载的映射文件:
SessionFactory sessionFactory = new Configuration().addClass(mypack.Customer.class).addClass(mypack.Order.class).buildSessionFactory();
如果使用xml配置文件,可以在配置文件中声明映射文件。
当通过Configuration的默认构造方法Configuration()来创建Configuration实例时,hibernate会到classpath中查找默认的hibernate.properties文件,如果找到,就把它的配置信息加载到内存中。在默认情况下,hibernate不会加载hibernate.cfg.xml文件,必须通过Configuration的configure()方法来显式加载hibernate.cfg.xml文件:SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Configuration的configure()方法会到classpath中查找hibernate.cfg.xml文件,如果找到,就把它的配置信息加载到内存中,如果同时存在hibernate.properties文件和hibernate.cfg.xml文件,那么hibernate.cfg.xml文件的内容会覆盖hibernate.properties文件的内容。在实际应用中,可以在hibernate.properties文件中设定默认的配置,然后在hibernate.cfg.xml文件中把与特定环境相关的配置放在里面。
如果希望hibernate从指定的XML文件中读取配置信息,可以调用Configuration.configure(String resource)方法:SessionFactory sessionFactory = new Configuration().configure(/netstore.cfg.xml").buildSessionFactory();这里的目录不能是相对目录,只能是相对于classpath的绝对目录。


c3p0相关配置代码:xml方式

<!-- 最大连接数 -->
<property name="hibernate.c3p0.max_size">20</property>

<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">5</property>

<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">120</property>

<!-- 最大的PreparedStatement的数量 -->
<property name="hibernate.c3p0.max_statements">100</property>

<!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->
<property name="hibernate.c3p0.idle_test_period">120</property>

<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.c3p0.acquire_increment">2</property>

<!-- 每次都验证连接是否可用 -->
<property name="hibernate.c3p0.validate">true</property>

properties方式:

hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase

hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect


相关文章