博客信息

hibernate综述

0
发布时间:『 2016-09-24 18:23』  博客类别:java框架  阅读(364) 评论()

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>、共用主键

 

         public class IdCard {

          private Integer id;

          private String no;

           private String name;

           private String addr;

           private Person person;


---------------------上面就是在持久化类中的做的,生成get/set方法------------

           共用主键的意思就是person表中的主键也是card表中的主键,比如说person中的id为2,那么在card表中的第一个身份证就是以2开始的,

     --------------我们来看主键的配置,在映射文件中-------------

            <hibernate-mapping package="com.sxt.hibernate.po">

           <class name="IdCard" table="t_cards">

      <id name="id" column="id_card" length="20">

      <generator class="foreign">

       <param name="property">person</param>

      </generator>

       </id>

----------------------

          <hibernate-mapping>

           <class name="com.sxt.hibernate.po.Person" table="t_persons">

<id name="id" column="p_id" length="20">

<generator class="native"></generator>

</id>

b>、唯一外键

 

          唯一外键说的就是在关系维护方会把非维护方的主键作为一个外键来使用,而自己的主键还是按照indentity或者native来设置,但是

 这个外键会有一个唯一性约束,unique约束,我们来看配置;


<!-- 引用person的主键作为card表中的外键,由于many有了unique的约束,所以也是一对一的出现 -->

<many-to-one name="person" column="p_id" unique="true"></many-to-one>

</class>

</hibernate-mapping>


      

10>、多对多映射

     a>、关联关系上没有附加属性

如果没有附加属性那么我们首先得确认持久化类所对应的表结构,确定关系维护方,比如订单和商品,订单是依赖商品的,所以订单作为关系

维护方,就是在他的映射文件上建立相应的关系,

----可以这样解释,一个商品对应多个订单,多个订单同样也对应多个商品

--------------持久化类的设计,单向的设计--------------

public class Order {

private Integer id;

private String name;

private String addr;

private String tel;

private Set<Product> product=new HashSet<Product>();


         ------------------------配置文件-----------------------

<set name="product" table="t_items">

<key column="order_id"></key>

<many-to-many class="Product" column="pro_id"></many-to-many>

</set>


        -----------------持久化类的设计,双向的-----------------


        public class Product {

private Integer id;

private String name;

private double price;

private Set<Order> order;


--------

public class Order {

private Integer id;

private String name;

private String addr;

private String tel;

private Set<Product> product=new HashSet<Product>();


-------------配置文件-------------

       

          这是order中的配置 》》<set name="product" table="t_items">

<key column="order_id"></key>

<many-to-many class="Product" column="pro_id"></many-to-many>

</set>


         这是product中的配置 》》

<set name="order" table="t_items">

<key column="pro_id"></key>

<many-to-many class="Order" column="order_id"></many-to-many>

</set>

         -------------注意::这里的出现的错误就是,我们在这里写的<many-to-many class="Order中的Order默认在配置的时候写的默认的

包,与前面的

        包保持一致,如果前面的类谢了全名,那么这里也得写全比如:

<hibernate-mapping package="com.sxt.hibernate.po">

<class name="Product" table="t_product">

-------下面的是全名

<hibernate-mapping>

<class name="com.sxt.hibernate.po.Product" table="t_product">


=====================一般测试的方法都有哪些=============================

1。保存非维持关系的一方,比如保存商品,testSaveProduct()

2。在保存订单的时候,同时保存商品-----

Order order1=new Order("小李","西安未央","455544");

        Order order2=new Order("小张","西安未央","455544");


order1.addPro(new Product(1));

order1.addPro(new Product(2));

order1.addPro(new Product(4));

         >>>new Product(1)|||这里要求在持久化类中得有一个构造参数,构造参数的方法是值传递一个id,就是为了保存关系维护方的同时保存

非维护方

3.还有就是getOrder中时候同时拿出product

4.删除订单的时候,看能不能删除订单所关联的商品,这里存在一个inverser,如果把它设置为true那么直接删除order就会跑出异常

如果不写或者写为false那么就会把商品直接删除

======做了双向关联以后

5.测试的方法是,我们在拿出商品的时候,getproduct()看能不能拿出order

 

b>、关联关系上附加有其它属性(如订单上购买的商品的数量) : 可以将多对多关系拆成两个一对多

   

关联上其他属性,比如商品的数量,那么我们会出现一个中间表,来存储这个东西,存储包括两张表的主键

本来是多对多,我们可以把它分开,

订单---购物项---商品

<many-to-one name="order" column="o_id"></many-to-one>

        <many-to-one name="product" column="pro_id"></many-to-one>


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>


关键字:   hibernate     框架  
Copyright © 2012-2017 yinbin.lan 版权所有   京ICP备16047123号