# hibernate框架 ### API 介绍 - Configuration:定位并读取映射文件的位置 - SessionFactory:单个数据库映射关系经过编译后的内存镜像,线程安全 - ConnectionProvider:生成JDBC连接的工厂(连接池) - Session:持久层管理器,单线程对象,隐藏了JDBC连接 - TransactionFactory:生成Transaction对象实例的工厂 - Transaction:指定原子操作单元范围的单线程对象 - Query和Criteria:对数据库及持久对象进行查询的接口 - Callback:允许用户程序能对一些事件的发生做出相应的操作 ### 配置映射关系 * 编写映射文件来定义映射关系:\*.hbm.xml文件,位于WEB-INF/classes目录中 * 通过注解映射 #### 文件 ```xml <hibernate-mapping> <class name="类的完全限定名" table="表名"> <!-- 主键标识 --> <id name="属性名"> <generator class="主键生成策略"></generator> </id> <property name="属性名" colmun="列名" type="数据类型"></property> </class> </hibernate-mapping> ``` 主键生成策略配置 * assigned: 主键由外部程序负责生成 * increment: 取出主键的最大值并加1 * identity: 由数据库实现自增长 * native: 由数据库自行判断 * uuid: 随机生成32位不相同的字符串 #### 注解 * @Entity 实体类 * @Table(name = "表名") 默认以类名作为表名 * @Id 声明属性为主键 * @GeneratedValue 表示主键是自动生成策略,一般和@Id一起使用。 * AUTO 默认选项,由数据库自动生成 * IDENTITY 由自己指定 * @Column(length=长度, nullable=是否允许为空, name="字段名") * @Lob 声明字段为 Clob 或 Blob 类型 * @Temporal(value=TemporalType.DATE) 做日期类型转换 DATE(日期), TIME(时间), TIMESTAMP(日期+时间) * @Transient 不进行持久化 ### 配置Hibernate ### xml文件 ``` <hibernate-configuration> <session-factory> <!-- 数据库配置信息 --> <property name="dialect">数据库方言</property> <property name="connection.driver_class">数据库驱动</property> <property name="connection.url">数据库地址</property> <property name="connection.username">用户名</property> <property name="connection.password">登录密码</property> <!-- 数据库其他配置 --> <property name="show_sql">是否显示sql语句</property> <property name="format_sql">是否格式化sql语句</property> <property name="connection.autocommit">是否自动提交</property> <!-- 导入持久类配置文件 --> <mapping resource="employee.hbm.xml"/> </session-factory> </hibernate-configuration> ``` 数据库方言:解决不同数据库之间的差异性 * MySQL: org.hibernate.dialect.MySQL5Dialect * SQL Server 2008: org.hibernate.dialect.SQLServer2008Dialect #### 属性文件 属性文件名为hibernate.properties,内部包含键值对。 ```txt hibernate.connection.usename 用户名 hibernate.connection.password 密码 hibernate.connection.url JDBC连接字符串 hibernate.dialect Hibernate方言类 hibernate.connection.driver_class JDBC驱动类 ``` ### 代码方式 ```java Configuration configuration = new Configuration(); configuration.addResoure(“mapping.xml”).setProperty(“connection.username”,”root”); …… ``` ### 数据库操作 1. 建立SessionFactory 2. 使用SessionFactory类的openSession方法来获得一个Session对象 3. 使用Session接口的beginTransation方法开始一个新事务 4. 使用Session接口的save方法保存实例 5. 如果成功,使用Transaction接口的commit方法提交事务,否则使用rollback方法回滚事务 6. 关闭Session对象 #### 建立会话工厂 ```java // Hibernate3 // 读hibernate.cfg.xml配置文件 Configuration config = new Configuration().configure(); // 建立SessionFactory SessionFactory sessionFactory = config.buildSessionFactory(); // Hibernate4 // 将Hibernate的配置或者服务等统一向ServiceRegistry注册后,才能生效 ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build(); SessionFactory sessionFactory = config.buildSessionFactory(serviceRegistry); // Hibernate5 config.addAnnotatedClass(User.class); ``` #### 获得一个Session对象 ```java session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); session.save(user); //保存Entity到数据库中 tx.commit(); session.close(); ``` Session对象不是线程安全的,多个用户请求不能并发。`getCurrentSession()`创建的session会绑定到当前线程,会在事务回滚或事物提交后自动关闭。事务配置:本地事务`<property name="hibernate.current_session_context_class">thread</property>`;全局事务(JTA事务)`<property name="hibernate.current_session_context_class">jta</property>` ```java public class HibernateUtil { private static final SessionFactory sessionFactory; public static SessionFactory getSessionFactory() { ...... } public static Session getSession(){ return getSessionFactory().getCurrentSession(); } } ``` #### HQL 面向对象的查询语言,查询以对象形式存在的数据,推荐的查询模式 ### Hibernate缓存 * SessionFactory缓存(应用缓存),二级缓存:存放元数据和预定义SQL,被所有session共享 * Session缓存(事务缓存),一级缓存:提高访问性能,保证缓存对象与数据库同步,保证不出现对象的死锁,多线程之间不能共享 #### get与load * get:首先在一级缓存中,通过实体类型和id进行查找。否则,依次查询二级缓存和数据库,没有找到返回null * load:首先查session缓存,看id对应的对象是否存在。如果缓存中没有这个对象,则创建代理,使用对象时查询二级缓存和数据库,如果数据库没有这条数据,抛出异常ObjectNotFoundException