Hibernate初体验(1)

来源:互联网 发布:淘宝专业版店铺装修 编辑:程序博客网 时间:2024/05/18 14:22

Hibernate是一个 Java 领域的持久化框架、ORM 框架。

对象的持久化

  • 狭义的理解,“持久化”仅仅指把对象永久保存到数据库中
  • 广义的理解,“持久化”包括和数据库相关的各种操作:
    保存:把对象永久保存到数据库中。
    更新:更新数据库中对象(记录)的状态。
    删除:从数据库中删除一个对象。
    查询:根据特定的查询条件,把符合查询条件的一个或多个对象从数据库加载到内存中。

ORM(Object/Relation Mapping): 对象/关系映射

ORM 主要解决对象-关系的映射,他的思想是将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。

Hibernate的配置与使用

注:这里不再讲述如何加入jar包以及必要的数据库驱动。
在类路径下创建Hibernate的配置文件,默认为 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.connection.username">root</property>        <property name="hibernate.connection.password">123456</property>        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>        <!-- 配置 hibernate 的基本信息 -->        <!-- hibernate 所使用的数据库方言 -->        <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>              <!-- 配置 C3P0 数据源 -->        <property name="hibernate.c3p0.max_size">10</property>        <property name="hibernate.c3p0.min_size">5</property>        <property name="c3p0.acquire_increment">2</property>        <property name="c3p0.idle_test_period">2000</property>        <property name="c3p0.timeout">2000</property>        <property name="c3p0.max_statements">10</property>        <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 mysql无效-->        <property name="hibernate.jdbc.fetch_size">100</property>        <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 mysql无效-->        <property name="jdbc.batch_size">30</property>        <!-- 执行操作时是否在控制台打印 SQL -->        <property name="hibernate.show_sql">true</property>        <!-- 是否对 SQL 进行格式化 -->        <property name="hibernate.format_sql">true</property>        <!-- 指定自动生成数据表的策略 -->        <!-- - create : 会根据 .hbm.xml  文件来生成数据表, 但是每次运行都会删除上一次的表 ,重新生成表, 哪怕二次没有任何改变 - create-drop : 会根据 .hbm.xml 文件生成表,但是SessionFactory一关闭, 表就自动删除 - update : 最常用的属性值,也会根据 .hbm.xml 文件生成表, 但若 .hbm.xml 文件和数据库中对应的数据表的表结构不同, Hiberante  将更新数据表结构,但不会删除已有的行和列 - validate : 会和数据库中的表进行比较, 若 .hbm.xml 文件中的列在数据表中不存在,则抛出异常-->        <property name="hibernate.hbm2ddl.auto">update</property>        <!-- 指定需要关联的 .hbm.xml 文件 -->        <mapping resource="com/atguigu/hibernate/helloworld/News.hbm.xml"/>    </session-factory></hibernate-configuration>

创建实体类:

public class News {    private Integer id;     private String title;    private String author;    private Date date;    public Integer getId() {         return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getTitle() {        return title;    }    public void setTitle(String title) {        this.title = title;    }    public String getAuthor() {        return author;    }    public void setAuthor(String author) {        this.author = author;    }    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    public News(String title, String author, Date date) {        super();        this.title = title;        this.author = author;        this.date = date;    }    public News() {    }

创建对象关系映射文件(对象关系映射文件要与实体类在同一目录下即同一个包内,切文件名称一致。实体是News.java,关系映射文件就为News.hbm.xml):

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.atguigu.hibernate.helloworld">    <class name="News" table="NEWS" dynamic-insert="true">        <id name="id" type="java.lang.Integer">            <column name="ID" />            <!-- 指定主键的生成方式, native: 使用数据库本地方式 -->            <generator class="native" />        </id>        <property name="title" not-null="true" unique="true"            index="news_index" length="50"            type="java.lang.String" column="TITLE" >        </property>        <property name="author" type="java.lang.String"            index="news_index">            <column name="AUTHOR" />        </property>        <property name="date" type="date">            <column name="DATE" />        </property>        <property name="desc"             formula="(SELECT concat(title, ',', author) FROM NEWS n WHERE n.id = id)"></property>        <property name="content">            <column name="CONTENT" sql-type="text"></column>        </property>        <property name="picture" column="PICTURE" type="blob"></property>    </class></hibernate-mapping>

测试代码:

        //1. 创建一个 SessionFactory 对象        SessionFactory sessionFactory = null;        //1). 创建 Configuration 对象: 对应 hibernate 的基本配置信息和 对象关系映射信息        Configuration configuration = new Configuration().configure();        //4.0 之前这样创建,但是buildSessionFactory()过时了。//      sessionFactory = configuration.buildSessionFactory();        //2). 创建一个 ServiceRegistry 对象: hibernate 4.x 新添加的对象        //hibernate 的任何配置和服务都需要在该对象中注册后才能有效.        ServiceRegistry serviceRegistry =                 new ServiceRegistryBuilder().applySettings(configuration.getProperties())                                            .buildServiceRegistry();        //3).        sessionFactory = configuration.buildSessionFactory(serviceRegistry);        //2. 创建一个 Session 对象        Session session = sessionFactory.openSession();        //3. 开启事务        Transaction transaction = session.beginTransaction();        //4. 执行保存操作        News news = new News("朝花夕拾", "鲁迅", new Date(new java.util.Date().getTime()));        session.save(news);        //5. 提交事务         transaction.commit();        //6. 关闭 Session        session.close();        //7. 关闭 SessionFactory 对象        sessionFactory.close();

上面的代码运行后,就会创建表并且插入一条数据。

创建持久化类的要求:

  • 提供一个无参的构造器:使Hibernate可以使用Constructor.newInstance() 来实例化持久化类
  • 提供一个标识属性(identifier property): 通常映射为数据库表的主键字段. 如果没有该属性,一些功能将不起作用,如:Session.saveOrUpdate()
  • 为类的持久化类字段声明访问方法(get/set): Hibernate对JavaBeans 风格的属性实行持久化。
  • 使用非 final 类: 在运行时生成代理是 Hibernate 的一个重要的功能. 如果持久化类没有实现任何接口, Hibnernate
    使用 CGLIB 生成代理. 如果使用的是 final 类, 则无法生成 CGLIB 代理.
  • 重写 eqauls 和 hashCode 方法: 如果需要把持久化类的实例放到 Set 中(当需要进行关联映射时), 则应该重写这两个方法

Session概述

  • Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载 Java
    对象的方法.
  • Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应. Session 能够在某些时间点,按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷新缓存(flush)
  • 站在持久化的角度, Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态. Session的特定方法能使对象从一个状态转换到另一个状态.

1.Session缓存:在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期。Session缓存可减少 Hibernate 应用程序访问数据库的频率。
例如:

 News news = (News) session.get(News.class, 1);System.out.println(news); News news2 = (News) session.get(News.class, 1);System.out.println(news2);

由于Session的魂村,这里只会发送一条select语句。
2.操作Session缓存
操作Session缓存

flush:Session 按照缓存中对象的属性变化来同步更新数据库,默认情况下 Session 在以下时间点刷新缓存:

  • 显式调用 Session 的 flush() 方法
  • 当应用程序调用 Transaction 的 commit()方法的时, 该方法先 flush ,然后在向数据库提交事务
  • 当应用程序执行一些查询(HQL, Criteria)操作时,如果缓存中持久化对象的属性已经发生了变化,会先 flush
    缓存,以保证查询结果能够反映持久化对象的最新状态

flush 缓存的例外情况: 如果对象使用 native 生成器生成 OID, 那么当调用 Session 的 save() 方法保存对象时, 会立即执行向数据库插入该实体的 insert 语句.
commit() 和 flush() 方法的区别:flush 执行一系列 sql 语句,但不提交事务;commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。
测试代码:

/**     * flush: 使数据表中的记录和 Session 缓存中的对象的状态保持一致. 为了保持一致, 则可能会发送对应的 SQL 语句.     * 1. 在 Transaction 的 commit() 方法中: 先调用 session 的 flush 方法, 再提交事务     * 2. flush() 方法会可能会发送 SQL 语句, 但不会提交事务.      * 3. 注意: 在未提交事务或显式的调用 session.flush() 方法之前, 也有可能会进行 flush() 操作.     * 1). 执行 HQL 或 QBC 查询, 会先进行 flush() 操作, 以得到数据表的最新的记录     * 2). 若记录的 ID 是由底层数据库使用自增的方式生成的, 则在调用 save() 方法时, 就会立即发送 INSERT 语句.      * 因为 save 方法后, 必须保证对象的 ID 是存在的!     */    @Test    public void testSessionFlush2(){        News news = new News("Java", "SUN", new Date());        session.save(news);    }    @Test    public void testSessionFlush(){        News news = (News) session.get(News.class, 1);        news.setAuthor("Oracle");//      session.flush();//      System.out.println("flush");        News news2 = (News) session.createCriteria(News.class).uniqueResult();        System.out.println(news2);    }

refresh(): 会强制发送 SELECT 语句, 以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!

News news = (News) session.get(News.class, 1);System.out.println(news);session.refresh(news); System.out.println(news); 

clear(): 清理缓存

 News news1 = (News) session.get(News.class, 1);session.clear();News news2 = (News) session.get(News.class, 1);

数据库的隔离级别

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

  • 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚,T1读取的内容就是临时且无效的.
  • 不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段,值就不同了.
  • 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1再次读取同一个表, 就会多出几行.

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题. 一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。
数据库提供的 4 种事务隔离级别:
事务隔离级别
Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED
Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ。
在 Hibernate 中设置隔离级别:
JDBC 数据库连接使用数据库系统默认的隔离级别. 在 Hibernate 的配置文件中可以显式的设置隔离级别. 每一个隔离级别都对应一个整数:
1. READ UNCOMMITED
2. READ COMMITED
4. REPEATABLE READ
8. SERIALIZEABLE
Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别

        <!-- 设置 Hibernate 的事务隔离级别 -->        <property name="connection.isolation">2</property>

持久化对象的状态

  • 临时对象(Transient):
  • 在使用代理主键的情况下, OID 通常为 null
  • 不处于 Session 的缓存中
  • 在数据库中没有对应的记录

  • 持久化对象(也叫”托管”)(Persist):

  • OID 不为 null
  • 位于 Session 缓存中
  • 若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应
  • Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
  • 在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

  • 临时对象删除对象(Removed):

    1. 在数据库中没有和其 OID 对应的记录
    2. 不再处于 Session 缓存中
    3. 一般情况下, 应用程序不该再使用被删除的对象
  • 游离对象(也叫”脱管”) (Detached):

    1. OID 不为 null
    2. 不再处于 Session 缓存中
    3. 一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录

对象的状态转换图

对象的状态转换图

Session的核心方法

  • save()方法:Session 的 save() 方法使一个临时对象转变为持久化对象。
    Session 的 save() 方法完成以下操作:把 News 对象加入到 Session 缓存中, 使它进入持久化状态;选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 另外在使用代理主键的情况下, setId() 方法为 News 对象设置 OID 使无效的.
    计划执行一条 insert 语句:在 flush 缓存的时候
    Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系. 当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID
News news = new News();news.setTitle("CC");news.setAuthor("cc");news.setDate(new Date());//news.setId(100);这是无效的 System.out.println(news);session.save(news);System.out.println(news);//news.setId(101); 这会发生异常的
  • persist()方法:当对一个 OID 不为 Null 的对象执行 save() 方法时, 会把该对象以一个新的 oid 保存到数据库中; 但执行 persist() 方法时会抛出一个异常(PersistentObjectException).
News news = new News();news.setTitle("EE");news.setAuthor("ee");news.setDate(new Date());news.setId(200); //抛异常session.persist(news);
  • Session 的 get() 和 load() 方法,都可以根据跟定的 OID 从数据库中加载一个持久化对象
    get VS load
    1. 执行 get 方法: 会立即加载对象.
      执行 load 方法, 若不使用该对象, 则不会立即执行查询操作, 而返回一个代理对象。 get 是 立即检索, load 是延迟检索.
    2. load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化代理对象之前已经关闭了 Session。
      1. 若数据表中没有对应的记录, Session 也没有被关闭. get 返回 null,load 若不使用该对象的任何属性, 没问题; 若需要初始化了, 抛出异常.
        @Test    public void testLoad(){        News news = (News) session.load(News.class, 10);        System.out.println(news.getClass().getName()); //      session.close();//      System.out.println(news);     }    @Test    public void testGet(){        News news = (News) session.get(News.class, 1);//      session.close();        System.out.println(news);     }

-Session 的 update() 方法

 //若更新一个持久化对象, 不需要显示的调用 update 方法. 因为在调用 //Transactioncommit() 方法时, 会先执行 session 的 flush 方法.News news = (News) session.get(News.class, 1);news.setAuthor("SUN"); session.update(news);//可省略,如果不做任何修改是不会发送update语句的
/** 更新一个游离对象, 需要显式的调用 session 的 update 方法. 可以把一个游离对象变为持久化对象**/News news = (News) session.get(News.class, 1);  transaction.commit();session.close();session = sessionFactory.openSession();transaction = session.beginTransaction();news.setAuthor("SUN"); //游离对象,需要显示调用update()session.update(news);

注意:1. 无论要更新的游离对象和数据表的记录是否一致, 都会发送 UPDATE 语句.
如何能让 updat 方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置
select-before-update=true (默认为 false). 但通常不需要设置该属性.

 2. 若数据表中没有对应的记录, 但还调用了 update 方法, 会抛出异常
News news = (News) session.get(News.class, 1);transaction.commit();session.close();news.setId(100);session = sessionFactory.openSession();transaction = session.beginTransaction(); news.setAuthor("SUN"); session.update(news);//抛异常
3. 当 update() 方法关联一个游离对象时,   如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常(NoUniqueObjectException). 因为在 Session 缓存中不能有两个 OID 相同的对象!
transaction.commit();session.close();session = sessionFactory.openSession();transaction = session.beginTransaction();News news2 = (News) session.get(News.class, 1);session.update(news);//抛出异常

Session 的 saveOrUpdate() 方法

News news = new News("FFF", "fff", new Date()); session.saveOrUpdate(news); //会进行保存操作,执行insert语句。news.setId(1);session.saveOrUpdate(news);//会进行更新,执行update操作

注意:
- 若 OID 不为 null, 但数据表中还没有和其对应的记录. 会抛出一个异常(StaleStateException).
- 了解: OID 值等于 id 的 unsaved-value 属性值的对象, 也被认为是一个游离对象

Session 的 merge() 方法

Session 的 delete() 方法

Session 的 delete() 方法既可以删除一个游离对象, 也可以删除一个持久化对象

 News news = new News();news.setId(11);session.delete(news); //会删除id为11的记录News news = (News) session.get(News.class, 163840);session.delete(news); //会删除id为163840的记录 

delete: 执行删除操作. 只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作。若 OID 在数据表中没有对应的记录, 则抛出异常
可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true,
使删除对象后, 把其 OID 置为 null(开发时用的不是特别多)

<!-- 删除对象后, 使其 OID 置为 null --><property name="use_identifier_rollback">true</property>

Session 的 evict() 方法

从 session 缓存中把指定的持久化对象移除

News news1 = (News) session.get(News.class, 1);News news2 = (News) session.get(News.class, 2); news1.setTitle("AA");news2.setTitle("BB");session.evict(news1); //不会发送new1的update语句。

通过 Hibernate 调用存储过程

session.doWork(new Work() {@Overridepublic void execute(Connection connection) throws SQLException {System.out.println(connection); String procedure = "{call testProcedure{}}";CallabStatement cstmt = connnection.prepareCall(procedure );cstmt.executeUpdate();              //调用存储过程. //和jdbc调用存储过程是一致的,也可以再这里做一些批量操作,要比直接用hibernate效率要高    }});

通过 Hibernate 调用存储过程

Hibernate 与数据库中的触发器协同工作时, 会造成两类问题
触发器使 Session 的缓存中的持久化对象与数据库中对应的数据不一致:触发器运行在数据库中, 它执行的操作对 Session 是透明的
Session 的 update() 方法盲目地激发触发器: 无论游离对象的属性是否发生变化, 都会执行 update 语句, 而 update 语句会激发数据库中相应的触发器
解决方案:
在执行完 Session 的相关操作后, 立即调用 Session 的 flush() 和 refresh() 方法, 迫使 Session 的缓存与数据库同步(refresh() 方法重新从数据库中加载对象)
在映射文件的的 元素中设置 select-before-update 属性: 当 Session 的 update 或 saveOrUpdate() 方法更新一个游离对象时, 会先执行 Select 语句, 获得当前游离对象在数据库中的最新数据, 只有在不一致的情况下才会执行 update 语句。

对象关系映射文件*.hbm.xml

Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系。在运行时 Hibernate 将根据这个映射文件来生成各种 SQL 语句,映射文件的扩展名为 .hbm.xml。
映射文件说明:
这里写图片描述
class 元素用于指定类和表的映射

  • name:指定该持久化类映射的持久化类的全类名
  • table:指定该持久化类映射的表名, Hibernate 默认以持久化类的类名作为表名
  • dynamic-insert: 若设置为 true, 表示当保存一个对象时, 会动态生成 insert 语句, insert
    语句中仅包含所有取值不为 null 的字段. 默认值为 false
  • dynamic-update: 若设置为 true, 表示当更新一个对象时, 会动态生成 update 语句, update
    语句中仅包含所有取值需要更新的字段. 默认值为 false
  • select-before-update:设置 Hibernate 在更新某个持久化对象之前是否需要先执行一次查询. 默认值为 false
  • batch-size:指定根据 OID 来抓取实例时每批抓取的实例数.
  • lazy: 指定是否使用延迟加载.
  • mutable: 若设置为 true, 等价于所有的 元素的 update 属性为 false,
    表示整个实例不能被更新. 默认为 true.
  • discriminator-value: 指定区分不同子类的值. 当使用
    元素来定义持久化类的继承关系时需要使用该属性

id节点:一般用如下的的形式就可以

<id name="id" type="java.lang.Long">    <column name="ID" />    <generator class="native" /></id>

property 节点用于指定类的属性和表的字段的映射
- name:指定该持久化类的属性的名字
- column:指定与类的属性映射的表的字段名. 如果没有设置该属性, Hibernate 将直接使用类的属性名作为字段名.
- type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁.如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型,然后自动使用与之对应的默认的 Hibernate 映射类型.
- not-null:若该属性值为 true, 表明不允许为 null, 默认为 false
- access:指定 Hibernate 的默认的属性访问策略。默认值为 property, 即使用 getter, setter
方法来访问属性. 若指定 field, 则 Hibernate 会忽略 getter/setter 方法, 而通过反射访问成员变量
- unique: 设置是否为该属性所映射的数据列添加唯一约束.
- index: 指定一个字符串的索引名称. 当系统需要 Hibernate 自动建表时, 用于为该属性所映射的数据列创建索引,从而加快该数据列的查询.
- length: 指定该属性所映射数据列的字段的长度
- scale: 指定该属性所映射数据列的小数位数, 对 double, float, decimal 等类型的数据列有效.
- formula:设置一个 SQL 表达式, Hibernate 将根据它来计算出派生属性的值. 派生属性:
并不是持久化类的所有属性都直接和表的字段匹配, 持久化类的有些属性的值必须在运行时通过计算才能得出来, 这种属性称为派生属性 使用formula 属性时 formula=“(sql)” 的英文括号不能少
Sql 表达式中的列名和表名都应该和数据库对应, 而不是和持久化对象的属性对应 如果需要在 formula 属性中使用参数, 这直接使用 where cur.id=id 形式, 其中 id 就是参数, 和当前持久化对象的 id 属性对应的列的 id 值将作为参数传入.

<!-- 映射派生属性 --><property name="desc" formula="(SELECT concat(AUTHOR, ': ', TITLE) FROM NEWS n WHERE n.ID= ID)"></property>

Java 类型, Hibernate 映射类型及 SQL 类型之间的对应关系

这里写图片描述
这里写图片描述

Java 时间和日期类型的 Hibernate 映射

1). 两个基础知识:
I. 在 Java 中, 代表时间和日期的类型包括: java.util.Date 和 java.util.Calendar.
此外, 在 JDBC API 中还提供了 3 个扩展了 java.util.Date 类的子类: java.sql.Date, java.sql.Time
和 java.sql.Timestamp, 这三个类分别和标准 SQL 类型中的 DATE, TIME 和 TIMESTAMP 类型对应
II. 在标准 SQL 中, DATE 类型表示日期, TIME 类型表示时间, TIMESTAMP 类型表示时间戳, 同时包含日期和时间信息.

2). 如何进行映射 ?
I. 因为 java.util.Date 是 java.sql.Date, java.sql.Time 和 java.sql.Timestamp 的父类, 所以 java.util.Date
可以对应标准 SQL 类型中的 DATE, TIME 和 TIMESTAMP
II. 基于 I, 所以在设置持久化类的 Date 类型是, 设置为 java.util.Date.
III. 如何把 java.util.Date 映射为 DATE, TIME 和 TIMESTAMP ?
可以通过 property 的 type 属性来进行映射:
例如:

<property name="date" type="timestamp">    <column name="DATE" /></property><property name="date" type="data">    <column name="DATE" /></property><property name="date" type="time">    <column name="DATE" /></property>

其中 timestamp, date, time 既不是 Java 类型, 也不是标准 SQL 类型, 而是 hibernate 映射类型.

映射组成关系

Hibernate 把持久化类的属性分为两种:

  1. 值(value)类型: 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期
  2. 实体(entity)类型: 有 OID, 可以被单独持久化, 有独立的生命周期

显然无法直接用 property 映射 pay 属性。Hibernate 使用 元素来映射组成关系, 该元素表明 pay 属性是 Worker 类一个组成部分, 在 Hibernate 中称之为组件。

<!-- 映射组成关系 --><component name="pay" class="Pay">     <!--元素指定组件属性所属的整体类. name: 整体类在组件类中的属性名-->     <parent name="worker"/>     <!-- 指定组成关系的组件的属性 -->     <property name="monthlyPay" column="MONTHLY_PAY"></property>     <property name="yearPay" column="YEAR_PAY"></property>     <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property></component>
0 0
原创粉丝点击