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缓存
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):
- 在数据库中没有和其 OID 对应的记录
- 不再处于 Session 缓存中
- 一般情况下, 应用程序不该再使用被删除的对象
游离对象(也叫”脱管”) (Detached):
- OID 不为 null
- 不再处于 Session 缓存中
- 一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录
对象的状态转换图
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- 执行 get 方法: 会立即加载对象.
执行 load 方法, 若不使用该对象, 则不会立即执行查询操作, 而返回一个代理对象。 get 是 立即检索, load 是延迟检索. - load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化代理对象之前已经关闭了 Session。
- 若数据表中没有对应的记录, Session 也没有被关闭. get 返回 null,load 若不使用该对象的任何属性, 没问题; 若需要初始化了, 抛出异常.
- 执行 get 方法: 会立即加载对象.
@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 方法. 因为在调用 //Transaction的 commit() 方法时, 会先执行 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 把持久化类的属性分为两种:
- 值(value)类型: 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期
- 实体(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>
- Hibernate初体验(1)
- Hibernate初体验(2)
- Hibernate的初体验
- hibernate初体验
- Hibernate初体验
- Hibernate Search 初体验
- Hibernate初体验
- Hibernate之初体验
- hibernate初体验
- hibernate初体验
- Hibernate初体验
- hibernate-初体验
- Hibernate+Webwork2分页初体验
- Hibernate之初体验一
- hibernate痛苦的初体验
- Hibernate 初体验 之 配置Hibernate
- hibernate学习笔记-1入门初体验对象持久化
- 体验Hibernate
- 99. Recover Binary Search Tree
- 学生成绩管理系统(数据结构之线性表实现)
- 最坏情况为线性时间的选择算法---算法导论学习笔记(2)
- PL/SQL基础语法
- C++继承解析
- Hibernate初体验(1)
- OllyDbg学习进度
- Ajax的原理和应用
- 《数据结构与算法分析java语言描述》知识点总结(1-2章)
- 20161108随笔
- MongoDB的安装与基本使用
- 【bzoj 2434】【codevs 1946】[Noi2011]阿狸的打字机(AC自动机)
- Android WiFi-ADB
- vim 复制和粘贴