Hibernate学习笔记

1>、Hibernate是数据访问层框架,是一个ORM(Object Relation Mapping)框架,作者为:Gavin King
2>、搭建Hibernate的开发环境
     a>、添加jar包:
     aa>、hibernatte开发包中/lib/required/所有jar
bb>、数据库的驱动程序
b>、定制hibernate的工作参数:在classpath根目录下创建一个hibernate.cfg.xml的配置文件
     模版从hibernate开发包中/documentation/manual/en-US/html_single/index.html教程第一章
    <?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据连接设定 -->
<property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:SXT</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>

<!-- 数据库连接池大小 -->
<property name="connection.pool_size">1</property>

<!-- SQL方言 -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

<!-- 禁用二级缓存  -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

<!--向控制台输出所有执行的SQL语句 -->
<property name="show_sql">true</property>
<!-- 自动建表 -->
<property name="hbm2ddl.auto">update</property>
<!-- 注册映射文件 -->
<mapping resource="com/sxt/hibernate/po/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
c>、设计持久化类(Employee),持化化类设计的规范为
       a>、public 非final
   b>、有一个OID属性,该属性唯一标识一个对象,基本类型建议使用包装类型
   c>、有无参的构造方法
   d>、属性有get/set方法
   e>、集合属性声明为接口类型,如Set,List
d>、完成持久化类的对象关系映射,在持久化类所在位置,建一个名字为:持久化类名.hbm.xml的映射文件
        <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name="com.sxt.hibernate.po.Employee" table="t_emps">
  <!-- 主键映射 -->
  <id name="id" column="emp_id">
<!-- 主键的生成策略 -->
<generator class="native"/>
  </id>
  <!-- 其它属性映射 -->
  <property name="empno" length="20" />
  <property name="name"  column="ename" length="30" not-null="true"/>
  <property name="sex"   length="2"/>
  <property name="job"   length="20"/>
  <property name="hiredate"  />
  <property name="salary"  column="sal" />
   </class>
</hibernate-mapping>
e>、使用Hibernate API完成数据库访问操作
       //读取hibernate.cfg.xml中的配置信息
Configuration cfg = new Configuration();
cfg.configure();
//创建SessionFactory
SessionFactory sf = cfg.buildSessionFactory();
//创建Session
Session session = sf.openSession();
//开始事务
Transaction tx = session.beginTransaction();
//执行数据库操作
session.save(emp1);
//提交事务
tx.commit();
//释放资源
session.close();

2>、使用Hibernate完成CRUD操作
        session.save();
session.get();
session.update();
session.delete();
session.createQuery(hql);

3>、主键的生成策略
        a>、由数据库生成: identity,sequence,native
b>、由程序生成:assigned  : 在调用save()方法,必须为对象的OID属性指定值
c>、由Hibernate生成: increment,uuid(主键为字符串类型),guid

4>、基于注解的映射方式
            @Entity
@Table(name="t_emp3")
public  class Employee3 {
@Id
@GeneratedValue
@Column(name="emp_id")
private Integer id; // OID:对象标识符,对应了数据库表的主键列
@Column(name="eno",length=20,nullable=false)
private String empno;
@Column(name="ename",length=20)
private String name;
@Column(length=2)
private String sex;
@Column(length=10)
private String job;

@Temporal(TemporalType.DATE)
private Date hiredate;

@Column(name="sal")
private double salary;
}

5>、持久化对象的三种状态

   临时态(Transient)         持久态(Persistent)             脱管态(Detached)
OID属性是否有值           没有                        有                            有
是否位于session的缓存      否                         是                            否
数据库中是否有对应的记录  没有                        有                            有

a>、save(),update(),saveOrUpdate(),get(),query.list()得到的对象都是持久态
b> 、持久态的对象如果其属性发生变化,在事务提交时hibernate会自动执行更新,将其状态同步至数据库,如果没有变化,即使调用update()方法也不会执行更新
c>、当执行get(),load()查询时,会首先从session的缓存中取,只有在session的缓存中没有时,才查询数据库
d>、如果将对象的引用设为null,emp=null;临时态,脱管态可以被垃圾回收,持久态不能
e>、与状态有关的方法
session.saveOrUpdate()
session.eveict();
session.clear();
session.flush();

6>、关联关系的映射
    a>、两个对象究竟是什么关系(一对多/多对一,一对一,多对多,继承)
    b>、该关系所对应的表结构
c>、对象模型怎么建
     A -> B
B -> A
A <-> B
     一般在关联关系的维护方(如果在保存A时,需要B的信息,则A为关联关系的维护)建单向关联
     如果要在关联关系的非维护方建关,就建双向关联,在非关联关系的维护方建关联关系,只影响查询操作
d>、关联关系映射怎么做
e>、在对对象执行crud操作时需注意什么
   aa>、执行保存操作时,关联关系的维护方需设定关联关系,关联对象必须为持久态或脱管态
        emp.setDept(new Dept(1));  //关联对象只需主键有值
       bb>、如果在对象上建了关联关系,并进行了映射,hibernate保证查询到的对象可以访问关联的对象 : e.getDept().getName();
   cc>、如果一个对象被另一个对象引用,则该对象不能删除(除非设定cascade)
7>、多对一/一对多关联
     a>、表结构:在Many方建外键
b>、双向关联中<set inverse="true"></set> insert="true" : 指定set不维持关联关系
c>、延迟加载(lazy) :只有当访问关联对象时,才执行SQL语句从数据库中查询对象
     只有session打开的情况下才能实现延迟加载,如果session关闭前,延迟属性没有初始化,关闭之后访问该属性会出异常
<many-to-one lazy="false/proxy"/>
<set lazy="true/false/extra"/> : 集合属性一定要使用延迟加载
      lazy="extra" : 在执行dept.getEmps().size()时,执行的sql为:select count(dept_id) from t_emps where dept_id=1
 
d>、抓取策略 : 如何查询关联对象
    <many-to-one fetch="select/join"/> : join 外连接抓取,在查询员工的同时使用外连接将员工的部门一块查出来,会覆盖lazy的设定
<set fetch="select/join/subselect"/> : subselect : 当执行List<Dept> depts = session.createQuery("from Dept").list();
                                                   depts.get(0).emps(); 会将所有部门的员工一块查出来

e>、级联操作:当对主控对象执行save,update,delete操作时,是否在关联对象上执行同样的操作

g>、<set order-by="salary desc"/> : order-by : 指定加载集合元素时,按哪个属性排序

8>、session.get()与load()方法的差别:(都是根据主键查询对象)
     get(): 立即加载,执行get()方法会立即发出SQL语句,执行数据库查询,查询到的就是目标类(Employee)的对象,如果数据不存在返回null
load():延迟加载, 执行load()方法不会发出SQL语句,只有在访问load()方法返回的对象的属性时,才执行查询,查询返回的是目标类的代理类对象,数据不存在抛异常

9>、一对一映射
     a>、共用主键

b>、唯一外键

    
     
10>、多对多映射
     a>、关联关系上没有附加属性
    public class Product {
private Integer id;
private String name;
private double salary;
}

public class Order {
private Integer id;
private String username; // 客户姓名
private String addr; // 送货地址
private String tel; // 联系电话
private Set<Product> products = new HashSet<Product>();
    }

<class name="Order" table="t_orders">
  <id name="id" column="order_id">
<generator class="native"/>
  </id>
  <property name="username"  length="10" />
  <property name="addr"  length="20" />
  <property name="tel"  length="20" />
  <!-- 多对多关联 -->
   <set name="products" table="t_items"  >
<key column="o_id"/> <!-- t_items表与t_orders表的连接列 -->
<many-to-many  class="Product" column="p_id"/> <!-- p_id是t_items表与t_products表的连接列 -->
   </set>  
    </class>
b>、关联关系上附加有其它属性(如订单上购买的商品的数量) : 可以将多对多关系拆成两个一对多
    public class Product {
private Integer id;
private String name;
private double salary;
}

    public class LineItem {
private Integer id;
private Order order; // 所属订单
private Product product; // 对应的商品
private int quantity = 1; // 数量
        }

<class name="LineItem" table="t_items">
  <id name="id" column="item_id">
<generator class="native"/>
  </id>
  <property name="quantity" />
  <many-to-one name="order" column="o_id"/>
  <many-to-one name="product" column="p_id"/>
    </class>

<class name="Order" table="t_orders">
  <id name="id" column="order_id">
<generator class="native"/>
  </id>
  <property name="username"  length="10" />
  <property name="addr"  length="20" />
  <property name="tel"  length="20" />
  <!-- 一对多关联 -->
   <set name="items" cascade="all">
  <key  column="o_id"/>
  <one-to-many class="LineItem"/>
   </set>
    </class>
11>、list映射
     a>、当需要保证元素的添加次序与获取次序一致时使用list,否则应用set,使用list时,元素在list中的次序会在数据库中存储下来
b>、list必须是关联关系的维护方
c>、
  <list name="products" table="t_items"  >
<key column="o_id"/> <!-- t_items表与t_orders表的连接列 -->
<list-index column="prod_seq"/> <!-- 指定记录产品在订单中次序的列名 -->
<many-to-many  class="Product" column="p_id"/> <!-- p_id是t_items表与t_products表的连接列 -->
   </list>
  

12>、继承映射
        Person : id,name,sex,age
Student extends Person : sno,score;
Teacher extends Person : title,salary;

       a>、每个类分层结构一张表(table per class hierarchy) [单表]
        id    name    sex   age  sno   score  title   salary    type[鉴别列]
1     张三     男    20  null   null   null    null      p
2     李四     女    15  sxt01  90     null    null      s
3     王五     男    30  null   null   教授    5000      t
aa>、优点:所有数据都在一张表中,crud速度比较快
bb>、所有子类属性不能有not null约束,当子类属性比较多时,可能会产生很多null值

   b>、每个子类一张表(table per subclass)
       t_persons
       id    name     sex   age 
1     张三     男    20 
2     李四     女    15 
3     王五     男    30 
      
   t_students
   id     sno     score
2     sxt01     90  
         
  t_teachers
           id   title   salary
            3    教授     5000
          
           bb>、缺点:子类的crud操作都访问至入两张表   

   c>、每个具体类一张表(table per concrete class)
       t_persons
    id    name    sex   age 
1     张三     男    20 

           t_students
   id    name    sex   age  sno   score
2     李四     女    15  sxt01  90  

           t_teachers
            id    name    sex   age   title   salary 
3     王五     男    30    教授    5000      

  aa>、所有表中主键值不能相同
 

13>、Hibernate的查询操作
     a>、QBC : Query By Criteria
     b>、Native SQL :
     c>、HQL查询


14>、批量处理
     a>、批量插入
    for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20,与JDBC批量设置相同
//flush a batch of inserts and release memory:
//将本批插入的对象立即写入数据库并释放内存
session.flush();
session.clear();
}
}

b>、批量更新与删除
        session = HibernateUtils.getSession();
session.beginTransaction();
//String hql = "update Employee e set e.salary=e.salary + 200 where e.salary<2000";
String hql = "delete from Employee e where e.salary < 2000";
Query query = session.createQuery(hql);
int rows = query.executeUpdate();
System.out.println("删除了" + rows + "条记录");
session.getTransaction().commit();

     c>、恢复scott的数据
aa>在sqlplus 下执行: @ D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\scott.sql

15、缓存 (将对象放入内存,提升查询的性能)
    a>、一级缓存
    session的缓存,对缓存对象的管理由hibernate实现,缓存的是所有持久态的对象,Hibernate不控制缓存中对象的数量,可能会出现内存溢出,所缓存对象的生命周期较短
b>、二级缓存
    SessionFactory的缓存,由第三方实现,hibernate只提供了存取缓存对象的API,在使用前需要打开与配置,所缓存对象的生命周期较长,经常被查询且很少会改变的对象适合放入二级缓存
    aa>、选择缓存供应商,在hibernate.cfg.xml中添加相关配置
<property name="cache.use_query_cache">true</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
<property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property>
    bb>、添加缓存供应商的jar包
cc>、准备缓存提供者的配置文件
dd>、指定需要放入二级缓存中的类
      aaa>、在类的映射文件中指定: <class name="Employee"><cache usage="read-only"/></class>
      bbb>、在hibernate.cfg.xml中指定
     <class-cache usage="read-only" class="com.sxt.hibernate.po.Employee"/>
c>、查询缓存
    缓存的是HQL属性查询的结果集,对实体查询只缓存主键值
select e.name,e.job,e.salary from Employee e where e.salary > 2000 and e.job='MANAGER'
        query.setCacheable(true) 



16、JPA : Java Persistence API  
    a>、JPA与Hibernate的关系
     JPA是一套持久化规范,不是一个持久化框架
Hibernate是JPA的实现者之一

b>、搭建JPA开发环境(Hibernate实现)
    aa>、添加Jar : 1)、原hibernate的所有jar包,2)、hibernate的lib\jpa\hibernate-entitymanager-4.3.2.Final.jar
    bb>、配置文件(classpath:META-INF/persistence.xml)
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="sxt">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- property的name与value属性的值由JPA的实现来定 -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="java"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>

c>、使用JPA完成CRUD操作
   persist();
   find();
   merge()
   remove();
d>、关联关系映射


17、
<property name="gender" not-null="true" length="5">
   <type name="org.hibernate.type.EnumType">
    <param name="enumClass">com.itqiang.model.Gender</param>
    <!--
     12为java.sql.Types.VARCHAR常量值,即保存枚举的字面值到数据库。如果不指定type参数,保存枚举的索引值(从0开始)到数据库
    -->
    <param name="type">12</param>
   </type>
</property>



   

你可能感兴趣的:(Hibernate)