好好学习,天天向上!

hibernate学习笔记

1.关系模型
 关系模型把世界看作是由实体(Entity)和联系(Relationship)构成的;在关系模型中实体通常是以表的形式来表现的。表的每一行描述
 实体的一个实例,表的每一列描述实体的一个特征或属性;所谓联系就是指实体之间的关系,即实体之间的对应关系;
2.ORM-对象关系映射
 ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中;它实现了Java应用中的对象到关系数据库中的表的自动的(和透明的)持久化;当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息等。而这些代码写起来总是重复的。
  个人建议:可以去看看Spring的JdbcTemplate
3.Hibernate-
 提供了强大的对象和关系数据库映射以及查询功能。

 持久化Java类必须遵循的原则:
     对JavaBeans风格的属性实行持久化/getter/setter/
     默认的构造方法->Constructor.newInstance()
     集合类型的属性,它的类型必须定义为集合的接口
     提供一个标识属性(identifier property)->如级联更新等(更新主键值的操作,该值由其它表的现有行中的外键列引用。在级联更新中,更新所有外键值以与新的主键值相匹配)
     ......

     持久化类(POJO)- *.hbm.xml -数据库结构(schema)【xdoclet/hbm2java(code generator)/SchemaExport(hbm2dll)/Middlegen】

 配置Hibernate:
  开发hibernate3.0必须的包:
   hibernate3.jar
   required:antlr、dom4j、CGLIB、asm、Commons Collections、Commons Logging、 EHCache->oscache
   Hibernate底层还需要Java Transaction API-jta.jar
  将\etc目录下的log4j.properties复制至Hibernate项目的Classpath下,并修改一下当中的log4j.logger.org.hibernate为error,也就是只在在错误发生时显示必要的讯息
   配置文件.xml/.properties
   hibernate.cfg.xml:

 1<?xml version="1.0" encoding="utf-8"?>
 2   <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
 3   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 4    <hibernate-configuration>
 5        <session-factory>
 6         <!-- 显示实际操作数据库时的SQL -->
 7      <property name="show_sql">true</property>
 8      <!-- SQL方言,这边设定的是MySQL -->
 9      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
10       <!-- JDBC驱动程序 -->
11      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
12      <!-- JDBC URL -->
13       <property name="connection.url">jdbc:mysql://localhost/demo</property>
14      <!-- 数据库使用者 -->
15      <property name="connection.username">root</property>
16      <!-- 数据库密码 --> 
17       <property name="connection.password">root</property>
18         <!-- 以下设置对象与数据库表格映像文件 -->
19     </session-factory>
20    </hibernate-configuration>
21


     *.hbm.xml-告诉 Hibernate您所定义的*实例如何映射至数据库表,以Use为例:user.hbm.xml-
    

 1 <?xml version="1.0" encoding="utf-8"?>
 2  <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"     
 3  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4   <hibernate-mapping>  
 5    <class name="com.db.hibernate.demo.User" table="user">    
 6     <id name="id" column="id" type="java.lang.Integer">
 7     <!-- 主键的生成方式由Hibernate根据数据库Dialect的定义来决定 -->
 8     <generator class="native" /> 
 9     </id>    
10     <property name="name" column="name" type="java.lang.String" />    
11     <property name="age" column="age" type="java.lang.Integer" />  
12    </class>
13  </hibernate-mapping>
14


    需要在Hibernate配置文件hibernate.cfg.xml中指明映像文件的位置
 详见eclipse的db工程
4.配置文件的问题:
 1.The content of element type "session-factory" must match "(property*,mapping*,(class-cache|collection-cache)*,event*,listener*)".
  解决:1.可能是文件编码问题;我的hibernate.cfg.xml是从ppt拷贝出来的,文件编码有问题;从正确的机器上拷贝一份文件或
  者尝试重新编码或者从网上拷贝一份正确的然后修改(正确的方法是参考etc目录下的xml模板)
   2.可能是元素(element type)的顺序问题
   3.可以将hibernate-configuration-3.0.dtd下载下来,对比一下,看哪里出错
 2.hibernate.cfg.xml和*.hbm.xml目前只能放到src根目录下,放到其他目录总报错
 3.关于xml dtd,正常下载的jar包中都会有dtd文件的,如hibernate-configuration-3.0.dtd;dom4j解析的时候会优先验证本地,如果本地有,则不会连接dtd指定的服务器地址;如果没有的话,可以去那地址下载dtd,放在本地或者将地址改为本地dtd的位置;当然eclipse也由一个选项,window->preference->xml catalog,可以添加;详见xml选项
5.Criteria
 Criteria对SQL进行封装,对于不甚了解SQL的开发人员来说,使用Criteria也可以轻易的进行各种数据的检索;Expression设定查询条件(Expression已被废弃,eclipse中添加hibernate的javadoc,方便查看)Criteria是对象导向式的查询方式,让不了解SQL的开发人员也可以轻易进行各项查询;但Criteria的API目前还不是很完善;Hibernate鼓励的查询方式,是透过HQL(Hibernate Query Language)来进行.
6.Query接口
7.hibernate配置文件-hibernate.cfg.xml(提供较好的结构与配置方式,hibernate建议使用,默认)/hibernate.properties
     注意:XML配置文件的位置必须在Classpath下;默认的XML配置文件名称是hibernate.cfg.xml;你可以自己指定配置文件:
     new Configuration().configure().configure("db.cfg.xml");
 在Hibernate下载档案中的etc目录下,有hibernate.cfg.xml与hibernate.properties可供设定参考properties档案中不包括映射文件的名称,需要编程方式:
 Configuration cfg = new Configuration().addClass("user.hbm.xml") .addClass(com.db.hibernate.demo.User.class);

 hibernate.properties:
 hibernate.show_sql = true
 hibernate.dialect = org.hibernate.dialect.MySQLDialect
 hibernate.connection.driver_class = com.mysql.jdbc.Driver
 hibernate.connection.url = jdbc:mysql://localhost/demo
 hibernate.connection.username = root
 hibernate.connection.password = root
8.Configuration-
 Configuration的实例管理Hibernate的配置信息,通常用于建立SessionFactory
 SessionFactory sessionFactory = config.buildSessionFactory();
9.SessionFactory-
 SessionFactory一旦建立,就被赋予当时Configuration的配置信息;即使改变Configuration也不会影响之前已建立的该实例,而会新建SessionFactory中包括了数据库配置及映射关系,它的建立相当复杂,所以使用时需考虑到重用已建立的SessionFactory实例SessionFactory是被设计为线程安全的(Thread-safe)
10.设定数据库连接-
 设定connection.pool_size是Hibernate默认的连接池设定;通常只用于开发阶段测试之用
 <!-- Hibernate 预设的Connection pool -->     
 <property name="connection.pool_size">2</property> 
     使用C3P0连接池,需要包含c3p0-*.jar;也可以使用Proxool或DBCP连接池(etc目录hibernate.properties中的配置例子来参考)使用Tomcat的话,您也可以通过它提供的DBCP连接池来取得连接-配置中加入connection.datasource属性
11.hibernate缓存
 Hibernate中Session level缓存会在使用主键加载资料或是延迟初始(Lazy Initialization) 时作用Session level缓存,Session会维护一个Map容器
 通过evict()将某个对象从缓存中移去,可以使用clear()清除缓存中的所有对象
 可以通过session的load方法和==来判断是否存在缓存

 Session在使用save()储存对象时,会将要储存的对象纳入Session level缓存管理,在进行大量数据储存时,缓存中的实例大量增加最后会导致OutOfMemoryError,可以每隔一段时间使用Session的 flush()强制储存对象,并使用clear()清除缓存

 1 1 Session session = sessionFactory.openSession();
 2 2  Transaction tx = session.beginTransaction(); 
 3 3  while(.)
 4 4  
 5 5   // 大量加载对象时的循环示意    
 6 6   .    
 7 7   session.save(someObject);    
 8 8   if(count % 100 == 0
 9 9   
1010    // 每100笔资料        
1111    session.flush(); 
1212    // 送入数据库        
1313    session.clear(); 
1414    // 清除缓存    
1515   }

1616  }
 
1717  tx.commit();
1818  session.close();
19


  配置中hibernate.jdbc.batch_size来控制每多少笔资料就送至数据库(MySQL中则不支持这个功能,sqlserver/oracle支持)
12.事务
 事务是一组原子(Atomic)操作(一组SQL执行)的工作单元;事务中的所有原子操作,不是全部执行成功,就是全部失败(即使只有一个失败,所有的原子操作也要全部撤消(回滚))JDBC中通过Connection的setAutoCommit和Commit方法管理事务,异常则回滚;Hibernate本身没有事务管理功能,它依赖于JDBC或JTA(java transaction api)的事务管理功能;默认是使用JDBC事务管理
 配置中添加:hibernate.transaction.factory_class属性来指定Transaction的工厂类别
 <property name="hibernate.transaction.factory_class"> org.hibernate.transaction.JDBCTransactionFactory</property> 
 Hibernate基于JDBC的事务管理只是对JDBC作了个简单的封装:

 1 try 
 2  {     
 3   session = sessionFactory.openSession();      
 4   Transaction tx = session.beginTransaction();     
 5   .      
 6   tx.commit();  // 必须commit才会更新数据库
 7  }
 
 8  catch(HibernateException e)
 9  {    
10   tx.rollback(); 
11  }


  在一开始的openSession()取得Session时,JDBC的Connection实例之AutoCommit就被设定为false,在 beginTransaction()时,会再度检查Connection实例的AutoCommit为false,在操作过程中,最后要commit (),否则的话对数据库的操作不会有作用,如果操作过程中因发生例外,则最后commit()不会被执行,之前的操作取消,执行rollback()可撤消之前的操作。要使用MySQL中的事务处理,必须建立事务表类型的表格例如InnoDB的表格
13.映射文件
 Hibernate 中将对象与数据库表格映射关系连接起来的是映射文件;通常以*.hbm.xml作为文件名称;手工撰写;通过工具程序从数据库表格自动生成;通过工具程序从Java类自动生成三部分:类名称与表格名称的映射;id属性与主键的映射;类属性与表格字段的映射

 1<?xml version="1.0" encoding="utf-8"?>
 2 <!DOCTYPE hibernate-mapping       PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"       
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
 4 <hibernate-mapping>    
 5  <!--类别名称与表格名称映像-->    
 6 <class name="onlyfun.caterpillar.User" table="user">      
 7  <!--id与主键映像-->      
 8  <id name="id" column="id" type="java.lang.Integer">        
 9   <generator class="native"/>      
10  </id>      
11  <!--类别属性与表格字段的映像-->      
12  <property name="name" column="name" type="java.lang.String"/>      
13  <property name="age" column="age" type="java.lang.Integer"/>    
14 </class>  
15 </hibernate-mapping> 
16


  注:
  1.Java的数据类型与数据库的数据类型并不是一对一对应的,为此Hibernate提供它自己的数据类型,作为Java数据类型与数
  据库数据类型的连接类型
  2.<generator>设定主键的生成方式;“native”表示由Hibernate自动根据Dialect选择采用 identity、hilo、sequence等作为主键生成方
  式;可以考虑采用uuid由Hibernate根据128位UUID算法(128- bit UUID algorithm)生成16进位制数值,并编码为32位长度的字符
  串
14.基本API
     1.Session-是Hibernate操作的基础;不是设计为线程安全;一个Session由一个线程使用;
     Hibernate在对数据库进行操作之前,必须先取得Session实例,相当于JDBC在对数据库操作之前,必须先取得Connection实例;过Session,可以对数据库进行新增、删除、更新;使用save()新增一条记录;使用get()或load()方法取得id为1的记录-User user = (User) session.get(User.class, new Integer(1));
 如果未能发现相符合的记录,则get()方法会返回null,而load()方法会丢出ObjectNotFoundException;在高级的应用中,load()方法可以返回代理对象,并可充分利用缓冲机制
 Hibernate 3中,取消了find()方法,您必须通过Query或Criteria来进行记录查询
     使用delete()删除资料
  1 User user = (User) session.get(User.class, new Integer(1));
   session.delete(user);
  2 Query q=session.createQuery(“delete User u where u.id=1”);
   q.executeUpdate();
  3 Session.delete(“from User u where u.id=1”);
     使用update()方法将对象中的资料更新至对应的数据表中
 Session提供了一个saveOrUpdate()方法:由定义映射文件时,设定<id>卷标的unsaved-value来决定
 Session如同在编写JDBC时需关心 Connection的管理,以有效的方法创建、利用与回收Connection,以减少资源的消耗,增加系统
 执行效率一样;SessionFactory是线程安全的(Thread-safe),然而Session则不是设计为线程安全的,所以试图让多个执行绪共享一个
 Session,将会发生资料共享而发生混乱的问题
 2.Session管理
  使用了ThreadLocal类来建立一个Session管理的辅助类,这是Hibernate的Session管理一个广为应用的解决方案
  Thread-Specific Stroage模式可以有效隔离线程所使用的资源,所以避开Session的多线程之间的资源共享问题
  ThreadLocal是*Thread-Specific Storage 模式*的一个运用实例
  Hibernate会在真正需要数据库操作时才(从连接池中)取得Connection
  在Web应用程序中,可以藉由Filter来进行Session管理,在需要的时候开启Session,并在Request结束之后关闭Session
 3.Criteria基本查询
  Criteria对SQL进行封装,让开发人员可以用对象的方式来对数据库进行操作
  Criteria criteria = session.createCriteria(User.class);
  // 查询user所有字段
  List<User> users = criteria.list();
  Criteria实际上只是个容器,如果想要设定查询条件,则要使用add()方法加入Restrictions的条件限制
  例如查询age大于20且小于40的资料:

1Criteria criteria = session.createCriteria(User.class);
2  criteria.add(Restrictions.gt("age"new Integer(20)));//greater than >
3  criteria.add(Restrictions.lt("age"new Integer(40)));//lesser than <
4  List<User> users = criteria.list();


  也可以使用逻辑组合来进行查询-criteria.add(Restrictions.or(Restrictions.eq(), Restrictions.isNull())
  sqlRestriction()方法来提供SQL语法作限定查询
  criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));//alias别名
  在SQL撰写时,不必再写WHERE
  criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));
  Restrictions的几个常用限定查询方法:eq/allEq/gt/ge/lt/le/between/like/in/and/or/sqlRestriction
 4.Criteria高级查询
  使用Criteria进行查询,并使用Order对结果进行排序
  criteria.addOrder(Order.asc("age"));//desc()
  setMaxResults()方法可以限定查询回来的记录数;setFirstResult()设定传回查询结果第一个记录的位置
  这两个配合起来,就可以实现简单的分页
  对查询结果进行统计动作,使用Projections的avg()、rowCount()、count()、max()、min()、countDistinct()等方法
  criteria.setProjection(Projections.avg("age"));
  可以配合Projections的groupProperty()来对结果进行分组
  criteria.setProjection(Projections.groupProperty("age"));
  想结合统计与分组功能,则可以使用ProjectionList

1ProjectionList projectionList = Projections.projectionList();
2   projectionList.add(Projections.groupProperty("age"));
3   projectionList.add(Projections.rowCount()); 
4   Criteria criteria = session.createCriteria(User.class);
5   criteria.setProjection(projectionList);


  使用Example对象,可以将一个已知的对象作为查询的依据
  criteria.add(Example.create(user));
  Criteria可以进行复合查询
  Criteria与Session绑定,其生命周期跟随着Session结束而结束;使用Criteria时进行查询时,每次都要于执行时期动态建立对象
  能够重复使用Criteria对象,在Hibernate 3.0中新增了DetchedCriteria对象;您可以先建立DetchedCriteria实例,并加入各种查询条
  件,并于需要查询时再与Session绑定,获得一个绑定Session的Criteria对象

1// 先建立DetchedCriteria对象
2   DetachedCriteria detchedCriteria=DetachedCriteria.forClass(User.class);
3   // 加入查询条件
4   detchedCriteria.add(Restrictions.ge("age",new Integer(25)));        
5   Session session = sessionFactory.openSession();
6   // 绑定Session并返回一个Criteria实例
7   Criteria criteria = detchedCriteria.getExecutableCriteria(session); 
8


    5.Query接口
  使用org.hibernate.Query接口的实例来进行查询;
  透过Query接口,您可以先设定查询参数,使用setXXX()等方法,将指定的参数值填入,而不用每次都撰写完整的HQL
  在设定参数值时,必须依照 ? 所设定的顺序,并使用对应类型的setXXX()方法
  也可以使用命名参数(Named Parameter)
  将HQL撰写在程序之;避免硬编码(Hard code)在程序之中,在需要修改HQL时就很方便;
  在*.hbm.xml中使用<query/>卷标,并在<![CDATA[与]] >之间撰写HQL,撰写的位置是在</hibernate-mapping>之前
  (CDATA-character data)

 1 <?xml version="1.0" encoding="utf-8"?>
 2  <!DOCTYPE hibernate-mapping      
 3  PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"       
 4  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
 5 <hibernate-mapping>    
 6  <class name="model.User" table="user">       
 7   <id name="id" column="id“ type="java.lang.Integer">         
 8   <generator class="native"/>      
 9   </id>      
10   <property name="name" column="name" type="java.lang.String"/>   
11   <property name="age" column="age" type="java.lang.Integer"/>   
12  </class>    
13  <query name=“model.QueryUser">       
14   <![CDATA[
15   select user.name from User as user where user.age >:minAge 
16   ]]>         
17  </query>  
18 </hibernate-mapping>
19


   <query>的name属性用来设定查询外部HQL时的名称依据
  Query query = session.getNamedQuery(“model.QueryUser");
  query.setInteger("minAge", 25); 
15.HQL
 1.HQL基本查询
  查询指定类对应表格的所有记录
  Query query = session.createQuery("from User"); //也可以指定类的全称
  List names = query.list();
  HQL本身不区分大小写,不过要注意类的名称必须区分大小写
  Hibernate会自动判定继承关系,如果查询的类是某类的父类,则会返回与父类、子类对应的所有表格记录
  针对某个属性作查询-Query query = session.createQuery("select user.name from User as user"); 
  查询两个以上的属性,查询的结果会以数组的方式返回
  Query query = session.createQuery("select user.age, user.name from User as user"); Object[] obj = (Object[]) iterator.next();
  如果User类提供有适当的构建方法,则可以在使用HQL时直接指定新建一个对象传回-
  Query query = session.createQuery("select new User(user.name, user.age) from User as user");
  List names = query.list();User user= (User) iterator.next(); //这个返回的User实例并未与数据库有任何关联
  使用distinct去除资料重复的记录-Query query = session.createQuery("select distinct user.age from User as user");
  在HQL中使用函数-Query query = session.createQuery("select count(*) from User as user"); 
  使用avg()取得属性的平均值-Query query = session.createQuery("select avg(user.age) from User as user");
  使用upper()函数将字符串转为大写:Query query = session.createQuery("select upper(user.name) from User as user"); 
 2.where 子句
  使用where子句来限定查询的条件,除了 = 运算之外,还有 >、>=、<、<=、!= 或 <>等比较运算
  Query query = session.createQuery("from User user where user.name=‘cjy'"); 
  where子句上进行表达式-Query query = session.createQuery("from User user where (user.age / 10 = 3)");
  在where子句上使用and、or-Query query = session.createQuery("from User user where (user.age > 20) and (user.name = ‘cjy')");
  is not nullL与is null则可以测试字段值是否为空值Query query = session.createQuery("from User user where user.name is not null");
  between可以测试字段值是否在指定的范围之内-session.createQuery("from User user where user.age between 20 and 30");
  使用in或not in来测试字段值是否在您指定的集合中-session.createQuery("from User user where user.name in(‘cjy', ‘abc')");
  like或not like可以让您进行模糊条件搜寻-session.createQuery("from User user where user.name like ‘c%'");
  查询结果使用order by进行排序-session.createQuery("from User user order by user.age");
  可使用desc反排序-session.createQuery("from User user order by user.age desc");
  同时指定两个以上的排序方式-
  session.createQuery("from User user order by user.age desc, user.name");//先按照"age"反序排,"age"相同,则按照"name"顺序排列
  使用GROUP BY子句,自动将指定的字段依相同的内容群组-
  session.createQuery("select user.sex, avg(user.age) from User user group by user.sex");
  结合having子句-session.createQuery("select user.sex, avg(user.age) from User user group by user.sex having avg(user.age) > 20");
  在Hibernate 3中,HQL新增了update与delete语句,可以直接使用HQL指定更新或删除
  update子句进行更新-session.createQuery("update User set name=‘abc' where name=‘cjy'");query.executeUpdate();
  delete子句进行资料删除-session.createQuery("delete User where name=‘cjy'");query.executeUpdate();
16.SQL支持
 Hibernate提供了对SQL的支持,您可以指定您所要建立的SQL,并将实体类与资料表格关联;
  // SQL,并指定别名为user

1String sql = "select {user.*} from User user where user.age > 20";
2  Session session = sessionFactory.openSession();
3  // 建立 SQLQuery
4  SQLQuery sqlQuery = session.createSQLQuery(sql);
5  // 将别名user与实体类User关联在一起
6  sqlQuery.addEntity("user", User.class);
7  Iterator iterator = sqlQuery.list().iterator();
8


   addEntity()是将实体类与别名连结在一起的方法,大括号指定要查询的记录
 也可以将SQL语句定义在映射文件中*.hbm.xml
 <sql-query name="model.QueryUser">    
 <![CDATA[                   
  select {user.*} from User user where user.age > 20             
 ]]>             
 <return alias="user" class="model.User"/>  
 </sql-query> 
  Query query = session.getNamedQuery(“model.QueryUser");
  Iterator iterator = query.list().iterator();
  可以设定查询参数;
   <sql-query name=“model.QueryUser">
   <![CDATA[
    select {user.*} from User user where user.age > :age
   ]]>
   <return alias="user" class=“model.User"/>
   </sql-query>
    Query query = session.getNamedQuery("model.QueryUser");
    query.setInteger("age", 20); 
 Hibernate 3的映射文件中新增了<sql-insert>、<sql-update>与<sql-delete>三个卷标,您可以在这三个卷标中使用SQL自定义您的
 INSERT、UPDATE、DELETE

1 <sql-insert>       
2   INSERT INTO user (name, age) VALUES (?, ?)              
3  </sql-insert>     
4  <sql-update>       
5   UPDATE user SET name=?, age=?, WHERE id=?              
6  </sql-update>      
7  <sql-delete>       
8    DELETE FROM user WHERE id=?              
9  </sql-delete>

    
  ? (参数) 对应的顺序是映像文件中属性出现的顺序
17.映射基础
     Hibernate中的实体对象可以分为三种状态:Transient、Persistent、Detached。
     Transient-如User类所衍生出之对象,在还没有使用save()之前都是暂存对象,这些对象还没有与数据库发生任何的关系,不对应于数据库中的任一条记录。 
     Persistent-当对象与数据库中的记录有对应关系,并且与Session实例有关联而Session 实例尚未关闭(close),则它是在Persistent状态;Persistent状态的对象对应于数据库中的一条记录,对象的id值与记录的主键值相同,并且Session实例尚未失效;在这期间您对对象的任何状态变动,在Session实例关闭(close)或Transaction实例执行commit()之后,数据库中对应的记录也会跟着更新Session实例关闭(close),则Persistent状态的对象会成为Detached状态;使用Session的实例delete()方法删除记录,Persistent状态的对象由于失去了对应的记录,则它会成为Transient状态。
     Detached-Detached状态的对象,其id与数据库的主键值对应;Detached状态的对象之任何属性变动,不会对数据库中的记录造成任何的影响;Detached状态的对象可以使用update()方法使之与数据库中的对应记录再度发生关联,此时Detached状态的对象会变为 Persistent状态。

     Transient与Detached状态的对象未受Hibernate持久层管理员管理,对这两个状态的对象作任何属性变动,不会对数据库中的记录有任何的影响;而Persistent状态的对象受Hibernate持久层管理,对对象的属性变动,在Session实例关闭(close)或 Transaction实例执行commit()之后,数据库中对应的记录也会跟着更新。在对象为Persistent时,如果对象的属性发生变化,并且尚未提交之前,对象所携带的资料称之为Dirty Data,Hibernate会在持久层
 维护对象的最近读取版本,并在资料提交时检查两个版本的属性是否有变化,如果有的话,则将数据库中的记录进行更新。

 对象识别:
  要有必要比较透过查询后两个对象的资料是否相同(例如当对象被储存至Set时)您必须重写 equals()与hashCode()
  重写方法之一,equals()与hashCode()的方法是根据数据库的identity,就是透过getId()方法取得对象的id值并加以比较

 1public class User 
 2  {    
 3   .     
 4   public boolean equals(Object o) 
 5   {        
 6    if(this == o) return true;       
 7    if(id == null || !(o instanceof User)) 
 8     return false;         
 9    final User user == (User) o;        
10    return this.id.equals(user.getId());    
11    }
     
12   public int hasCode() 
13   {        
14    return id == null ? System.identityHashCode(this):id.hashcode();    
15   }
 
16  }

17

  
  上面的例子是个不被鼓励的例子,因为当一个对象被new出来而还没有save()时,它并不会被赋予id值,这时候就不适用这
  个方法;
 比较被采用的方法是根据对象中真正包括的的属性值来作比较;
 可以使用org.apache.commons.lang.builder.EqualsBuilder与 org.apache.commons.lang.builder.HashCodeBuilder来协助定义equals()与
 hashCode();
  Return new EqualsBuilder().append(this.name,user.getName()).append(this.phone, user.getPhone()).isEquals();
  return new HashCodeBuilder().append(this.name).append(this.phone).toHashCode();
18.实体映射/集合映射/关系映射/继承映射/缓存/锁定/回调与拦截/工具
19.Annotation-
 可以不通过*.hbm.xml,完全通过annotation搞定
 hibernate.cfg.xml-
 <!-- 以下设置对象与数据库表格映像类别 -->
        <mapping class="com.db.hibernate.demo.User"/>

 实体标识,主键生成,以及相关映像,都可以使用Annotation来完成;

 1@Entity
 2 @Table(name="user"// 非必要,在表格名称与类别名称不同时使用
 3 public class User
 4 {
 5  @Id
 6  @GeneratedValue(strategy=GenerationType.AUTO)
 7   private Integer id;
 8
 9  @Column(name="name"// 非必要,在字段名称与属性名称不同时使用
10  private String name;
11  
12  @Column(name="age"
13  private Integer age; // 非必要,在字段名称与属性名称不同时使用
14    
15   // 必须要有一个预设的建构方法
16    // 以使得Hibernate可以使用Constructor.newInstance()建立对象
17   public User() {    }
18 }

19


  注意:import javax.persistence.*中的注解

 使用Annotation时,需要的是AnnotationConfiguration类;

1// 需要AnnotationConfiguration读取Annotation讯息
2  Configuration config = new AnnotationConfiguration().configure();
3  // 根据 config 建立 SessionFactory
4  // SessionFactory 将用于建立 Session
5   SessionFactory sessionFactory = config.buildSessionFactory();
posted @ 2012-12-18 14:38  忍性而为  阅读(357)  评论(0编辑  收藏  举报
好好学习,天天向上!