hibernatehibernate入门


备注

SessionFactory bean负责创建,维护,关闭和刷新TransactionManager要求它创建的所有数据库会话。这就是我们将SessionFactory装入DAO并通过它运行所有查询的原因。

新Hibernate用户提出的最大问题之一是“我的更改何时会被提交?”当您考虑TransactionManager如何与SesisonFactory工作时,答案才有意义。退出使用@Transactional注释的服务方法时,将刷新并提交您的数据库更改。这样做的原因是,交易应该代表一个不间断工作的单一“单位”。如果设备出现问题,则假设设备发生故障并且所有更改都应该回滚。因此,当您退出最初调用的服务方法时, SessionFactory将刷新并清除会话。

这并不是说在交易进行时它也不会刷新和清除会话。例如,如果我调用服务方法添加5个对象的集合并返回数据库中对象的总数,则SessionFactory将意识到查询( SELECT COUNT(*) )要求更新状态准确,并且因此,在运行计数查询之前,将刷新5个对象的添加。执行可能看起来像这样:

版本

文档链接发布日期
4.2.0 http://hibernate.org/orm/documentation/4.2/ 2013-03-01
4.3.0 http://hibernate.org/orm/documentation/4.3/ 2013年12月1日
5.0.0 http://hibernate.org/orm/documentation/5.0/ 2015年9月1日

使用XML的简单hibernate示例

要使用XML为配置设置一个简单的hibernate项目,您需要3个文件,hibernate.cfg.xml,每个实体的POJO和每个实体的EntityName.hbm.xml。以下是使用MySQL的示例:

的hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
   </property>
   <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
   </property>

   <property name="hibernate.connection.url">
      jdbc:mysql://localhost/DBSchemaName
   </property>
   <property name="hibernate.connection.username">
      testUserName
   </property>
   <property name="hibernate.connection.password">
      testPassword
   </property>

   <!-- List of XML mapping files -->
   <mapping resource="HibernatePractice/Employee.hbm.xml"/>

</session-factory>
</hibernate-configuration>
 

DBSchemaName,testUserName和testPassword都将被替换。如果它在包中,请确保使用完整的资源名称。

Employee.java

package HibernatePractice;

public class Employee {
    private int id;
    private String firstName;
    private String middleName;
    private String lastName;
    
    public Employee(){
        
    }
    public int getId(){
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
    public String getFirstName(){
        return firstName;
    }
    public void setFirstName(String firstName){
        this.firstName = firstName;
    }
    public String getMiddleName(){
        return middleName;
    }
    public void setMiddleName(String middleName){
        this.middleName = middleName;
    }
    public String getLastName(){
        return lastName;
    }
    public void setLastName(String lastName){
        this.lastName = lastName;
    }
}
 

Employee.hbm.xml

<hibernate-mapping>
   <class name="HibernatePractice.Employee" table="employee">
      <meta attribute="class-description">
         This class contains employee information. 
      </meta>
      <id name="id" type="int" column="empolyee_id">
         <generator class="native"/>
      </id>
      <property name="firstName" column="first_name" type="string"/>
      <property name="middleName" column="middle_name" type="string"/>
      <property name="lastName" column="last_name" type="string"/>
   </class>
</hibernate-mapping>
 

同样,如果类在包中,则使用完整的类名packageName.className。

拥有这三个文件后,您就可以在项目中使用hibernate了。

使用XML Configuration设置Hibernate

我在类路径的某处创建了一个名为database-servlet.xml 的文件。

最初,您的配置文件将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

</beans>
 

您会注意到我导入了txjdbc Spring命名空间。这是因为我们将在此配置文件中大量使用它们。

您要做的第一件事是启用基于注释的事务管理( @Transactional )。人们在Spring中使用Hibernate的主要原因是Spring将为您管理所有事务。将以下行添加到配置文件中:

<tx:annotation-driven />
 

我们需要创建一个数据源。数据源基本上是Hibernate用来持久保存对象的数据库。通常,一个事务管理器将具有一个数据源。如果您希望Hibernate与多个数据源通信,那么您有多个事务管理器。

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="" />
    <property name="url" value="" />
    <property name="username" value="" />
    <property name="password" value="" />
</bean>
 

这个bean的类可以是实现javax.sql.DataSource 任何东西,所以你可以自己编写。此示例类由Spring提供,但没有自己的线程池。一个流行的替代方案是Apache Commons org.apache.commons.dbcp.BasicDataSource ,但还有很多其他的。我将解释下面的每个属性:

  • driverClassName :JDBC驱动程序的路径。这是一个特定数据库的 JAR,应该可以在类路径中使用。确保您拥有最新版本。如果您使用的是Oracle数据库,则需要OracleDriver。如果你有一个MySQL数据库,你需要一个MySQLDriver。看看你是否能找到你需要的驱动程序但快速谷歌应该给你正确的驱动程序。

  • url :数据库的URL。通常这将类似于jdbc\:oracle\:thin\:\path\to\your\databasejdbc:mysql://path/to/your/database 。如果你四处寻找你正在使用的数据库的默认位置,你应该能够找到它应该是什么。如果您收到带有org.hibernate.HibernateException: Connection cannot be null when 'hibernate.dialect' not set 消息的HibernateException org.hibernate.HibernateException: Connection cannot be null when 'hibernate.dialect' not set 并且您遵循本指南时, org.hibernate.HibernateException: Connection cannot be null when 'hibernate.dialect' not set ,则您的URL有90%的可能性是错误的,有5%的几率您的数据库未启动,并且您的用户名/密码错误的概率为5%。

  • username :使用数据库进行身份验证时使用的用户名。

  • password :使用数据库进行身份验证时使用的密码。

接下来,就是设置SessionFactory 。这是Hibernate用来创建和管理事务,并实际与数据库进行对话的事情。它有很多配置选项,我将在下面解释。

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="au.com.project />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.use_sql_comments">true</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
        </props>
    </property>
</bean>
 
  • dataSource :您的数据源bean。如果您更改了dataSource的Id,请在此处进行设置。

  • packagesToScan :要扫描的包以查找JPA注释对象。这些是会话工厂需要管理的对象,通常是POJO并使用@Entity 注释。有关如何在Hibernate中设置对象关系的更多信息, 请参见此处

  • annotatedClasses (未显示):如果Hibernate不是全部在同一个包中,您还可以提供一个类列表供Hibernate扫描。您应该使用packagesToScanannotatedClasses 但不能同时使用两者。声明如下:

<property name="annotatedClasses">
    <list>
        <value>foo.bar.package.model.Person</value>
        <value>foo.bar.package.model.Thing</value>
    </list>
</property>
 
  • hibernateProperties :这里有无数的精心记录 。您将使用的主要内容如下:
  • hibernate.hbm2ddl.auto :最热门的Hibernate问题之一详述了这个属性。 查看更多信息 。我通常使用validate,并使用SQL脚本(对于内存)设置我的数据库,或者事先创建数据库(现有数据库)。
  • hibernate.show_sql :Boolean flag,如果为true Hibernate会将它生成的所有SQL打印到stdout 。您还可以通过在日志管理器中设置log4j.logger.org.hibernate.type=TRACE log4j.logger.org.hibernate.SQL=DEBUG 来配置您的记录器,以显示绑定到查询的值(我使用log4j )。
  • hibernate.format_sql :布尔标志,将导致Hibernate将SQL打印到stdout。
  • hibernate.dialect (未显示,有充分理由):很多旧的教程向您展示如何设置它将用于与数据库通信的Hibernate方言。 Hibernate 可以根据您使用的JDBC驱动程序自动检测要使用的方言。由于有大约3种不同的Oracle方言和5种不同的MySQL方言,我将这个决定留给Hibernate。有关Hibernate支持的完整方言列表, 请参阅此处

您需要声明的最后两个bean是:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
    id="PersistenceExceptionTranslator" />

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
 

PersistenceExceptionTranslator 将特定于数据库的HibernateExceptionSQLExceptions 转换为可由应用程序上下文理解的Spring异常。

TransactionManager bean控制事务和回滚。

注意:您应该将SessionFactory bean自动装入DAO中。

无XML的Hibernate配置

这个例子来自这里

package com.reborne.SmartHibernateConnector.utils;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class LiveHibernateConnector implements IHibernateConnector {

    private String DB_DRIVER_NAME = "";
    private String DB_URL = "jdbc:h2:~/liveDB;MV_STORE=FALSE;MVCC=FALSE";
    private String DB_USERNAME = "sa";
    private String DB_PASSWORD = "";
    private String DIALECT = "org.hibernate.dialect.H2Dialect";
    private String HBM2DLL = "create";
    private String SHOW_SQL = "true";
    
    private static Configuration config;
    private static SessionFactory sessionFactory;
    private Session session;
    
    private boolean CLOSE_AFTER_TRANSACTION = false;

    public LiveHibernateConnector() {
        
        config = new Configuration();

        config.setProperty("hibernate.connector.driver_class",         DB_DRIVER_NAME);
        config.setProperty("hibernate.connection.url",                 DB_URL);
        config.setProperty("hibernate.connection.username",         DB_USERNAME);
        config.setProperty("hibernate.connection.password",         DB_PASSWORD);
        config.setProperty("hibernate.dialect",                     DIALECT);
        config.setProperty("hibernate.hbm2dll.auto",                 HBM2DLL);
        config.setProperty("hibernate.show_sql",                    SHOW_SQL);
    
        /*
         * Config connection pools
         */

        config.setProperty("connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
        config.setProperty("hibernate.c3p0.min_size", "5");
        config.setProperty("hibernate.c3p0.max_size", "20");
        config.setProperty("hibernate.c3p0.timeout", "300");
        config.setProperty("hibernate.c3p0.max_statements", "50");
        config.setProperty("hibernate.c3p0.idle_test_period", "3000");
        
        
        /**
         * Resource mapping
         */
        
//        config.addAnnotatedClass(User.class);
//        config.addAnnotatedClass(User.class);
//        config.addAnnotatedClass(User.class);
    
        sessionFactory = config.buildSessionFactory();
    }


    public HibWrapper openSession() throws HibernateException {
        return new HibWrapper(getOrCreateSession(), CLOSE_AFTER_TRANSACTION);
    }


    public Session getOrCreateSession() throws HibernateException {
        if (session == null) {
            session = sessionFactory.openSession();
        }
        return session;
    }

    public void reconnect() throws HibernateException {
        this.sessionFactory = config.buildSessionFactory();
    }

    
}
 

请注意,使用最新的Hibernate这种方法效果不佳(Hibernate 5.2版本仍允许此配置)