zoukankan      html  css  js  c++  java
  • 复习hiernate

     Configuration

    Configuration 类负责管理 Hibernate 的配置信息

    包括如下内容:1,Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。2,持久化类与数据表的映射关系(*.hbm.xml 文件)。

     

    创建 Configuration 的两种方式

    属性文件(hibernate.properties)
           Configuration cfg = new Configuration();

    Xml文件(hibernate.cfg.xml)

    加载默认名称的配置文件(hibernate.cfg.xml)
           Configuration cfg = new Configuration().configure();

    或加载指定名称的配置文件:
           Configuration cfg = new Configuration().configure(“myhibernate.cfg.xml”);

     SessionFactory

    Configuration对象根据当前的配置信息生成 SessionFactory 对象。SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存)。 相关代码如下:

       Configuration cfg = new Configuration().configure();

       SessionFactory sessionFactory = cfg.buildSessionFactory();

    SessionFactory是线程安全的。

    SessionFactory是生成Session的工厂:
           Session session = sessionFactory.openSession();

    构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象。

     

    Session(一次与数据库的会话)

    Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 中有一个缓存,显式执行flush()方法之前,所有的持久层操作的数据都缓存在 session 对象处。(相当于 JDBC 中的 Connection)

    持久化类与 Session 关联起来后就具有了持久化的能力。

    Session是线程不安全的

    Session 类的一些方法:

    取得持久化对象的方法: get() load()

    持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()

    开启事务: beginTransaction().

    管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等

     Transaction

    代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。

    代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
    Transaction tx = session.beginTransaction();

    常用方法:

    commit():提交相关联的session实例

    rollback():撤销事务操作

    wasCommitted():检查事务是否提交

    QueryCriteria接口

    都是查询接口,Query实例包装了HQL查询语句,hql是面向对象的,他引用类名及类的属性名,而不是表名和字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更面向对象,他擅长执行动态查询。

    Hibernate的运行过程

    Hibernate的运行过程如下:

    1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,

    2、并用这些信息生成一个SessionFactory对象,

    3、然后从SessionFactory对象生成一个Session对象,

    4、并用Session对象生成Transaction对象;

        A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;

        B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。

     

     动创建表:(hibernate.cfg.xml中配置)

    <property name="hbm2ddl.auto">update</property>

    create:先删除,再创建

    update:如果表不存在就创建,不一样就更新,一样就什么都不做。在开发                   的时候使用较多。

    create-drop:初始化时创建表,SessionFactory执行close()时删除 表。

    validate:验证表结构是否一致,如果不一致,就抛异常。部署时可以使用

    对持久化对象的要求

    提供一个无参的构造器。使Hibernate可以使用Constructor.newInstance() 来实例化持久 化类。

    提供一个标识属性(identifier property)。通常映射为数据库表的主键字段。如果没有该 属性,一些功能将不起作用,如:Session.saveOrUpdate()。

    为类的持久化类的字段声明访问方法(get/set)。Hibernate对JavaBeans风格的属性实行        持久化。

    使用非final类。在运行时生成代理是Hibernate的一个重要的功能。如果持久化类没有 实现任何接口,Hibnernate 使用 CGLIB 生成代理。如果使用的是 final 类,则无法生    成CGLIB代理。

    重写eqauls()和hashCode()方法。如果需要把持久化类的实例放到Set中(当需要进行    关联映射时),则应该重写这两个方法。

    OID

    为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫做对象标识(Object identifier-OID)。

    使用基本数据类型和包装类型的区别

    基本数据类型和包装类型对应的hibernate映射类型相同(映射是一样的),例:

    propertye (默认值):

    表明hibernate通过getXXX和setXXX来访问类属性。推荐使用。提高域模型透明性。

    field

    hibernate通过java反射机制直接访问类属性。对于没有get与set方法的属性可设置该访问策略。

    noop

    它映射Java持久化类中不存在的属性,即主要用于HQL(用query接口测试,使用hql语句)中,当数据库中有某列,而实体中不存在的情况。

     

    OID,唯一性的标志

    关系数据库用主键区分是否是同一条记录。

    Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值。

     

    主键必备条件:

    1,不能为null。

    2,唯一,不能重复。

    3,永远不会改变。

    自然主键和代理主键

    自然主键:把具有业务含义的字段作为主键叫做自然主键。

    代理主键:不具备业务含义的字段,该字段一般取名为“id”。(推荐)

     

    关系数据库按主键区分不同记录

     

    把主键定义为自动增长类型

    在my SQL中,把字段设为auto_increment类型,数据库会自动为主键赋值。

    在ms SQL server中,把字段设为identity类型,数据库会自动为主键赋值。

     

    oracle从序列(sequence)中获取自动增长的描述符

    create sequence seq_customer increment by 2 start with 1

    insert into customers  values(seq_customer.curval,’..’)

     

    java与Hibernate如何区分对象

    Java语言按内存地址(==)或equals()方法区分不同的对象

     

    Hibernate中用对象表示符(OID)来区分对象

    OID是关系数据库中的主键在java对象模型中的等价物。在运行时,hibernate根据OID来维持java对象和数据库记录的对应关系。

    Hibernate使用OID来区分对象,不是equals()方法!所以不重写持久化类的hashCode()与equals()方法Hibernate也可以正确运行(但要放到HashSet等集合中时要注意需要重写这两个方法)。

    iD generator元素配置说明

    配置示例:

    <id name=“id” type=“long” column=“ID”>
    
          <generator class=“increment” />
    
    </id>

     

    <id>元素说明:

    设定持久化类的 OID 和表的主键的映射,可以有以下属性:

    name: 标识持久化类 OID 的属性名 

    column: 设置标识属性所映射的数据列的列名(主键字段的名字).

    unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值来区分当前持久化类的对象是否为临时对象,在Hibernate3中几乎不再需要.

    type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型

    Java 的基本数据类型和包装类型对应相同的 Hibernate 映射类型. 基本数据类型无法表达 null, 所以对于持久化类的 OID 推荐使用包装类型

     

    <generator>元素说明

    设定持久化类设定标识符生成器,可以有一个class属性:

    class: 指定使用的标识符生成器全限定类名或其缩写名。

     

    <generator>元素的class属性可以指定的值说明(主键生成策略)

    主键生成器

    描述

    increment

    适用于代理主键。由hibernate自动以递增的方式生成表识符,每次增量为1。

    identity

    适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数据类型。

    sequence

    适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。

    hilo

    适用于代理主键。Hibernate根据hign/low算法生成标识符。Hibernate把特定表的字段作为“hign”值。默认情况下,采用hibernate_unique_key表的next_hi字段。

    native

    适用于代理主键。根据底层数据库对自动生成表示符的能力来选择identity、sequence、hilo

    uuid.hex

    适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。

    assigned

    适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为private的。尽量避免使用自然主键。

     

    increment

     

    increment 标识符生成器由 Hibernate 以递增的方式为代理主键赋值

    Hibernate 会先读取表中的主键的最大值,向表中插入记录时, 就在 max(id) 的基础上递增,增量为1。

    适用范围:

    由于 increment生存标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。

    适用于只有单个 Hibernate 应用进程访问同一个数据库的场合,在多线程情况下会有问题(线程不安全)。

    OID必须为long、int或 short 类型,如果把OID定义为byte类型,在运行时会抛出异常

    identity

     

     

    identity 标识符生成器由底层数据库来负责生成标识符, 它要求底层数据库把主键定义为自动增长字段类型。

    适用范围:

    由于 identity 生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2、 Mysql、MSSQLServer、Sybase等。

    OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。

    sequence

     

     

    sequence  标识符生成器利用底层数据库提供的序列来生成标识符.

    Hibernate 在持久化一个 News 对象时, 先从底层数据库的 news_seq 序列中获得一个唯一的标识号, 再把它作为主键值

    适用范围:

    由于 sequence 生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB2 Oracle 等。

    OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。

    hilo

    (在hilo中这些关键字都不能修改)

    hilo 标识符生成器由 Hibernate 按照一种 high/low 算法*生成标识符, 它从数据库的特定表的字段中获取 high 值.

    Hibernate 在持久化一个 News 对象时, 由 Hibernate 负责生成主键值. hilo 标识符生成器在生成标识符时, 需要读取并修改 HI_TABLE 表中的 NEXT_VALUE 值.

    适用范围:

    由于 hilo 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统

    OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常

    native (在开发中用得最多)

     

    native 标识符生成器依据底层数据库对自动生成标识符的支持能力, 来选择使用 identity, sequence 或 hilo 标识符生成器.

    适用范围:

    由于 native 能根据底层数据库系统的类型, 自动选择合适的标识符生成器, 因此很适合于跨数据库平台开发

    OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常

      

     Hibernate映射类型

    内置映射类型

    Hibernate

    java

    sql

    取值范围

    integer int

    int Integer

    INTEGER

    4

    long

    long Long

    BIGINT

    8

    short

    short Short

    SMALLINT

    2

    byte

    byte Byte

    TINYINT

    1

    float

    float Float

    FLOAT

    4

    double

    double Double

    DOUBLE

    8

    big_decimal

    java.math.BigDecinimal

    NUMERIC

    8位含2位小数部分

    character

    char Character String

    CHAR(1)

    定长字符

    string

    String

    VARCHAR

    变长串

    boolean

    boolean Boolean

    BIT

    布尔

    yes_no

    boolean Boolean

    CHAR(1)

    布尔

    true_false

    boolean Boolean

    CHAR(1)

    布尔

     

    java时间和日期类性

    Hibernate

    java

    sql

    取值范围

    date

    util.Date sql.Date

    DATE

    YYYY-MM-DD

    time

    util.Date sql.Time

    TIME

    HH:MM:SS

    timestamp

    util.Date sql.timestamp

    TIMESTAMP

    YYYYMMDDHHMMSS

    calendar

    java.util.Calendar

    TIMESTAMP

    YYYYMMDDHHMMSS

    calendar_date

    java.util.Calendar

    DATE

    YYYY-MM-DD

     

    大对象类型的映射

    Hibernate

    java

    sql

    binary

    byte[]

    VARBINARY(BLOB)

    text

    String

    CLOB

    serializable

    实现类

    BARBINARY(BLOB)

    clob

    sql.Clob

    CLOB

    blob

    sql.Blob

    BLOB

     

    不允许以上类型来定义OID

     

     

    (Hibernate Reference3.2.2中有)JDBC 类 java.sql.Clob 和 java.sql.Blob的映射。某些程序可能不适合使用这个类型,因为blob 和 clob 对象可能在一个事务之外是无法重用的。(而且, 驱动程序对这种类型的支持充满着补丁和前后矛盾。)

    JDK自带的个别java类的映射类型

    Hibernate

    java

    sql

    class

    java.lang.Class

    VARCHAR

    locale

    java.util.Locale

    VARCHAR

    timezone

    java.util.TimeZone

    VARCHAR

    currency

    java.util.Currency

    VARCHAR

     

    集合属性大致有两种:

    单纯的集合属性,如像List、Set或数组等集合属性

    Map结构的集合属性,每个属性值都有对应的Key映射

     

    集合映射的元素大致有如下几种:

    list:        用于映射List集合属性

    set:               用于映射Set集合属性

    map:             用于映射Map集合性

    array:             用于映射数组集合属性

    bag:              用于映射无序集合

    idbag:            用于映射无序集合,但为集合增加逻辑次序

    使用集合属性时,一定要使用接口,而不能声明为具体的实现类。

    因为经过Session操作后,集合就变成了Hibernate自己的集合实现类

    Set

    但Set是无序,不可重复的集合。

     

      <class name="Teacher" table="t_teacher">
    
            <id name="id" column="id" type="int">
    
            <generator class="native"/>
    
            </id>
    
            <property name="name" column="name" type="string" length="20"></property>
    
               <set name="course" table="t_teacher_course" order-by="caurse DESC">
    
                      <key column="teacherId"></key>
    
                      <element type="string" column="caurse" ></element>
    
               </set>
    
        </class>

    order-by 影响是查询顺序(使用较多)

    Sort可以影响插入顺序,但是必须是有序集合例如treeset list

    测试程序

    public class TeacherDao {
    
           private static SessionFactory  sf;
    
           static{
    
                  Configuration cfg =  new Configuration();
    
                  cfg.configure();
    
                  cfg.addClass(Teacher.class);
    
                  sf = cfg.buildSessionFactory();
    
           }
    
           @Test
    
           public void save() throws Exception{
    
                  Set<String> set  = new HashSet<String>();
    
                  set.add("java软件开发");
    
                  set.add("C语言");
    
                  set.add("MySql数据库");
    
                 
    
                  Teacher teacher =  new Teacher();
    
                  teacher.setName("张三");
    
                  teacher.setCourse(set);
    
                 
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         session.save(teacher);
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
                 
    
                 
    
           }
    
           @Test
    
           public void getById() throws Exception{
    
                  Teacher teacher = null;
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         teacher = (Teacher) session.get(Teacher.class, 1);
    
                         System.out.println(teacher.getId());
    
                         System.out.println(teacher.getName());
    
                         System.out.println(teacher.getCourse().toString());
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
                 
    
                 
    
           }
    
          
    
    }

     

     

     

    注:映射 Set 集合属性时,如果 element 元素包括 not-null = “true” 属性,则集合属性表以关联持久化类的外键和元素列作为联合主键,否则该表没有主键。但 List 集合属性不会,List 集合属性总是以外键列和元素此序列作为联合主键。

    在实际应用中,我遇到要求没有顺序不重复的情况很多,所以一般set集合。

     

    List是有序集合,可以重复

    因此持久化到数据库时必须增加一列来表示集合元素的次序。

    集合属性只能以接口声明(当持久化某个实例时, Hibernate 会自动把程序中的集合实现类替换成 Hibernate 自己的集合实现类),因此下面代码中,schools的类型能是List,不能是ArrayList,

     

    映射说明

    list元素要求用list-index的子元素来映射有序集合的次序列。

    集合的属性的值会存放有另外的表中,须以外键关联,用 Key 元素来映射外键列。

    当集合元素是基本数据类型及其包装类, 字符串或日期类型时使用 element 来映射集合属性

     

    <list name="course" table="t_teacher_course">
    
                      <key column="teacherId"></key>
    
                      <list-index column="indx"></list-index>不使用index关键字
    
                      <element type="string" column="caurse" length="100"></element>
    
               </list>

     

     

    测试程序:

     

    @Test
    
           public void save() throws Exception{
    
                  List<String> list = new ArrayList<String>();
    
                  list.add("java软件开发");
    
                  list.add("C语言");
    
                  list.add("MySql数据库");
    
                  Teacher teacher =  new Teacher();
    
                  teacher.setName("张三");
    
                  teacher.setCourse(list);
    
                 
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         session.save(teacher);
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
                 
    
                 
    
           }

    生成的表及插入的数据

     

     

    数组

    数组属性的映射和 List 的处理方式基本一致

    数组使用 <array> 元素完成完成映射

    <array name="course" table="t_teacher_course">
    
                      <key column="teacherId"></key>
    
                      <list-index column="indx"></list-index>
    
                      <element type="string" column="course" length="100"></element>
    
               </array>

    代码:

    @Test
    
           public void save() throws Exception{
    
                 
    
                  String[] array = new String[]{"java软件开发1","C语言","MySql数据库"};
    
                  Teacher teacher =  new Teacher();
    
                  teacher.setName("张三");
    
                  teacher.setCourse(array);
    
                 
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         session.save(teacher);
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
                 
    
                 
    
           }

     

    Bag的特性是:允许重复的元素,但无序。在Java的标准API中并没有提供Bag容器,Hibernate提供自己的Bag实现,允许您将List映射为Bag。

     

    bag元素既可以为List集合属性映射,也可以为Collection集合属性映射。

    不管是哪种集合属性,使用bag元素都将被映射成无序集合,而集合属性对应的表没有主键。

    Bag 元素只需要 key 元素来映射外键列,使用 element 元素来映射集合属性的每个元素。

    <bag name="course" table="t_teacher_course">
    
                      <key column="teacherId"></key>
    
                      <element type="string" column="caurse" ></element>
    
               </bag>

    测试程序:

     
    
    @Test
    
           public void save() throws Exception{
    
                  List<String> list = new ArrayList<String>();
    
                  list.add("java软件开发");
    
                  list.add("C语言");
    
                  list.add("MySql数据库");
    
                  Teacher teacher =  new Teacher();
    
                  teacher.setName("张三");
    
                  teacher.setCourse(list);
    
                 
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         session.save(teacher);
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
           }
    
     

     

    Map不仅需要映射属性值,还需要映射属性Key。

    Hibnernate 将以外键列和Key列作为联合主键。

    Map集合属性使用map元素映射,该元素需要key和map-key两个子元素

    key子元素用于映射外键列,

    map-key子元素则用于映射Map集合的Key。

    map-key和element元素都必须确定type属性 

     

     

    <map name="course" table="t_teacher_course">
    
                      <key column="teacherId"></key>
    
                      <map-key type="string" column="kemu" length="100"></map-key>
    
                      <element type="string" column="course" length="100"></element>
    
               </map>

    代码实现:

    public void save() throws Exception{
    
                 
    
                  Map<String, String> map = new HashMap<String, String>();
    
                 
    
                  map.put("科目1:", "java软件开发1");
    
                  map.put("科目2:", "C语言");
    
                  Teacher teacher =  new Teacher();
    
                  teacher.setName("张三");
    
                  teacher.setCourse(map);
    
                 
    
                  Session session =  sf.openSession();
    
                  Transaction tc = null  ;
    
                  try {
    
                         tc  = session.beginTransaction();
    
                         session.save(teacher);
    
                         tc.commit();
    
                  } catch (Exception e) {
    
                         tc.rollback();
    
                         throw e;
    
                  }finally{
    
                         session.close();
    
                  }
    
           }

    哦对了忘记说一个事情 我这里面的初始化方法是比较老的那种新的请参见 不同版本的 api

  • 相关阅读:
    面试金典——模式匹配
    浅谈C语言中的联合体
    android recovery模式及ROM制作
    模拟键盘输入 : SendMessage, keybd_event, PostKeybdMessage
    在游戏中使用keybd_event的问题
    keybd_event函数用法
    C语言清空输入缓冲区的N种方法对比
    深究“字节对齐”的原因
    字节对齐
    网络安装CentOS 5.3
  • 原文地址:https://www.cnblogs.com/hwcs/p/7425912.html
Copyright © 2011-2022 走看看